@seer-ai/seer-vue 0.1.0-beta.5 → 0.1.0-beta.6
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 +1 -0
- package/dist/content.d.ts +10 -0
- package/dist/index.css +1 -1
- package/dist/index.js +256 -180
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -65,6 +65,7 @@ async function submit() {
|
|
|
65
65
|
<a v-if="seg.kind === 'link'" :href="seg.href" target="_blank" rel="noopener noreferrer">{{
|
|
66
66
|
seg.label
|
|
67
67
|
}}</a>
|
|
68
|
+
<img v-else-if="seg.kind === 'image'" :src="seg.href" :alt="seg.alt" loading="lazy" />
|
|
68
69
|
<span v-else>{{ seg.value }}</span>
|
|
69
70
|
</template>
|
|
70
71
|
</p>
|
package/dist/content.d.ts
CHANGED
|
@@ -5,6 +5,16 @@ export type ContentSegment = {
|
|
|
5
5
|
kind: 'link';
|
|
6
6
|
href: string;
|
|
7
7
|
label: string;
|
|
8
|
+
} | {
|
|
9
|
+
kind: 'image';
|
|
10
|
+
href: string;
|
|
11
|
+
alt: string;
|
|
12
|
+
} | {
|
|
13
|
+
kind: 'price';
|
|
14
|
+
value: string;
|
|
15
|
+
} | {
|
|
16
|
+
kind: 'strong';
|
|
17
|
+
value: string;
|
|
8
18
|
};
|
|
9
19
|
export declare function linkAnchorLabel(prefix: string): string | null;
|
|
10
20
|
export declare function toContentSegments(content: string): ContentSegment[];
|
package/dist/index.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.seer-chat[data-v-
|
|
1
|
+
.seer-chat[data-v-dc651545]{display:grid;gap:18px;max-width:720px;min-height:640px;padding:0;overflow:hidden;color:#18212f;background:radial-gradient(circle at 18% 0%,rgba(71,106,255,.14),transparent 32%),linear-gradient(180deg,#fff,#f7f9fd);border:1px solid rgba(127,143,170,.28);border-radius:28px;box-shadow:0 24px 70px #151f3429}.seer-chat__header[data-v-dc651545]{display:flex;gap:16px;align-items:flex-start;justify-content:space-between;padding:22px 22px 18px;color:#fff;background:linear-gradient(135deg,#141f34f5,#243f76f0),#172033}.seer-chat__header h2[data-v-dc651545]{margin:0;font-size:22px;letter-spacing:-.03em}.seer-chat__header p[data-v-dc651545],.seer-chat__empty[data-v-dc651545],.seer-chat__status[data-v-dc651545]{margin:4px 0 0;color:#5f6f89;font-size:14px}.seer-chat__header p[data-v-dc651545]{max-width:34ch;color:#ffffffb8}.seer-chat__messages[data-v-dc651545]{display:grid;gap:12px;align-content:start;min-height:330px;max-height:470px;padding:18px 18px 4px;overflow-y:auto}.seer-chat__empty[data-v-dc651545]{display:grid;place-items:center;min-height:260px;padding:0 28px;color:#66748a;text-align:center;border:1px dashed rgba(127,143,170,.38);border-radius:22px;background:#ffffff9e}.seer-chat__message[data-v-dc651545]{display:grid;gap:6px;max-width:min(86%,520px);padding:13px 15px;border:1px solid rgba(127,143,170,.16);border-radius:18px 18px 18px 6px;background:#ffffffe0;box-shadow:0 12px 28px #151f3414}.seer-chat__message--user[data-v-dc651545]{justify-self:end;color:#fff;border-color:transparent;border-radius:18px 18px 6px;background:linear-gradient(135deg,#285cff,#1d45c9);box-shadow:0 14px 30px #1f5eff3d}.seer-chat__role[data-v-dc651545]{font-size:12px;font-weight:700;opacity:.75}.seer-chat__body[data-v-dc651545]{display:flex;flex-direction:column}.seer-chat__line[data-v-dc651545]{margin:0;white-space:pre-wrap;overflow-wrap:anywhere}.seer-chat__line[data-v-dc651545]:not(:last-child){margin-bottom:5px}.seer-chat__line[data-v-dc651545]:empty{height:7px}.seer-chat__strong[data-v-dc651545]{font-weight:700}.seer-chat__price[data-v-dc651545]{color:#e0331d;font-weight:600}.seer-chat__message--user .seer-chat__price[data-v-dc651545]{color:#ffe2dc}.seer-chat__link[data-v-dc651545]{color:#1f5eff;font-weight:600;text-decoration:underline;text-underline-offset:2px;overflow-wrap:anywhere}.seer-chat__link[data-v-dc651545]:hover{color:#173fb3}.seer-chat__message--user .seer-chat__link[data-v-dc651545]{color:#fff}.seer-chat__image-button[data-v-dc651545]{display:block;padding:0;background:transparent;border:0;cursor:zoom-in}.seer-chat__image-button[data-v-dc651545]:not(:disabled):hover{transform:none}.seer-chat__image[data-v-dc651545]{display:block;max-width:100%;margin:6px 0;border-radius:12px;border:1px solid rgba(127,143,170,.22);transition:filter .16s ease}.seer-chat__image-button:hover .seer-chat__image[data-v-dc651545]{filter:brightness(.96)}.seer-chat__lightbox[data-v-dc651545]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1000;display:grid;place-items:center;padding:32px;background:#0a0f1ad1;cursor:zoom-out;animation:seer-chat__fade-in-dc651545 .14s ease}.seer-chat__lightbox-image[data-v-dc651545]{max-width:min(92vw,1200px);max-height:90vh;object-fit:contain;border-radius:12px;box-shadow:0 30px 80px #00000080}.seer-chat__lightbox-close[data-v-dc651545]{position:fixed;top:18px;right:22px;display:grid;place-items:center;width:40px;height:40px;color:#fff;font-size:26px;line-height:1;background:#ffffff24;border-radius:50%}.seer-chat__lightbox-close[data-v-dc651545]:not(:disabled):hover{background:#ffffff3d}@keyframes seer-chat__fade-in-dc651545{0%{opacity:0}to{opacity:1}}.seer-chat__error[data-v-dc651545],.seer-chat__handoff[data-v-dc651545]{margin:0 18px;padding:10px 12px;border-radius:14px}.seer-chat__error[data-v-dc651545]{color:#8a1f11;background:#fff0ed}.seer-chat__handoff[data-v-dc651545]{color:#704600;background:#fff7db}.seer-chat__form[data-v-dc651545]{display:grid;gap:11px;margin:0 18px 18px;padding:14px;background:#fff;border:1px solid rgba(127,143,170,.26);border-radius:22px;box-shadow:0 18px 38px #151f3417}.seer-chat__label[data-v-dc651545]{font-size:13px;font-weight:700}.seer-chat textarea[data-v-dc651545]{width:100%;box-sizing:border-box;min-height:92px;padding:14px;color:inherit;line-height:1.55;background:#f8fafd;border:1px solid transparent;border-radius:16px;outline:none;resize:vertical;transition:background .16s ease,border-color .16s ease,box-shadow .16s ease}.seer-chat button[data-v-dc651545]{color:inherit;font-weight:700;border:0;cursor:pointer;transition:transform .16s ease,box-shadow .16s ease,opacity .16s ease}.seer-chat button[data-v-dc651545]:not(:disabled):hover{transform:translateY(-1px)}.seer-chat button[data-v-dc651545]:disabled{cursor:not-allowed;opacity:.5}.seer-chat button[data-v-dc651545]:focus-visible,.seer-chat textarea[data-v-dc651545]:focus-visible{border-color:#1f5eff6b;box-shadow:0 0 0 4px #1f5eff21}.seer-chat__clear-button[data-v-dc651545]{flex:0 0 auto;padding:8px 11px;color:#ffffffc7;font-size:12px;background:transparent;border:1px solid rgba(255,255,255,.18)!important;border-radius:12px}.seer-chat__clear-button[data-v-dc651545]:not(:disabled):hover{color:#fff;background:#ffffff1a;box-shadow:none}.seer-chat__stop-button[data-v-dc651545]{padding:8px 11px;color:#6c3b12;font-size:12px;background:#fff1df;border-radius:12px}.seer-chat__send-button[data-v-dc651545]{display:inline-flex;gap:8px;align-items:center;justify-content:center;min-width:86px;padding:10px 14px;color:#fff;background:linear-gradient(135deg,#1f5eff,#173fb3);border-radius:14px;box-shadow:0 12px 24px #1f5eff38}.seer-chat__send-button[data-v-dc651545]:not(:disabled):hover{box-shadow:0 14px 28px #1f5eff47}.seer-chat__hint[data-v-dc651545]{margin-right:auto;color:#7a879a;font-size:12px}.seer-chat__composer-footer[data-v-dc651545]{display:flex;gap:8px;align-items:center;justify-content:flex-end}
|
package/dist/index.js
CHANGED
|
@@ -1,102 +1,102 @@
|
|
|
1
|
-
import { hasInjectionContext as
|
|
2
|
-
function
|
|
3
|
-
const n = e.fetcher ?? fetch, t = e.model ?? "seer",
|
|
4
|
-
let
|
|
1
|
+
import { hasInjectionContext as K, inject as D, ref as y, defineComponent as U, computed as B, onBeforeUnmount as M, openBlock as h, createElementBlock as _, createElementVNode as f, toDisplayString as C, unref as g, createCommentVNode as T, Fragment as R, renderList as I, normalizeClass as q, withModifiers as A, withDirectives as z, withKeys as F, vModelText as V } from "vue";
|
|
2
|
+
function X(e) {
|
|
3
|
+
const n = e.fetcher ?? fetch, t = e.model ?? "seer", s = e.now ?? (() => Math.floor(Date.now() / 1e3));
|
|
4
|
+
let r, a = 0;
|
|
5
5
|
return {
|
|
6
|
-
async chat(
|
|
7
|
-
const
|
|
6
|
+
async chat(l, i = {}) {
|
|
7
|
+
const c = l.stream ?? !1, o = await v(), m = {
|
|
8
8
|
"Content-Type": "application/json"
|
|
9
9
|
};
|
|
10
|
-
|
|
11
|
-
const
|
|
10
|
+
o && (m.Authorization = `Bearer ${o}`);
|
|
11
|
+
const k = await n(e.endpoint, {
|
|
12
12
|
method: "POST",
|
|
13
|
-
headers:
|
|
14
|
-
signal:
|
|
13
|
+
headers: m,
|
|
14
|
+
signal: i.signal,
|
|
15
15
|
body: JSON.stringify({
|
|
16
|
-
model:
|
|
17
|
-
messages:
|
|
18
|
-
stream:
|
|
19
|
-
conversation_id:
|
|
20
|
-
metadata:
|
|
16
|
+
model: l.model ?? t,
|
|
17
|
+
messages: l.messages,
|
|
18
|
+
stream: c,
|
|
19
|
+
conversation_id: l.conversationId,
|
|
20
|
+
metadata: l.metadata
|
|
21
21
|
})
|
|
22
22
|
});
|
|
23
|
-
if (!
|
|
24
|
-
throw new Error(await
|
|
25
|
-
if (
|
|
26
|
-
return
|
|
27
|
-
const
|
|
28
|
-
return
|
|
23
|
+
if (!k.ok)
|
|
24
|
+
throw new Error(await P(k));
|
|
25
|
+
if (c)
|
|
26
|
+
return G(k, i.onDelta);
|
|
27
|
+
const w = await k.json();
|
|
28
|
+
return j(w);
|
|
29
29
|
}
|
|
30
30
|
};
|
|
31
|
-
async function
|
|
31
|
+
async function v() {
|
|
32
32
|
if (!e.sessionEndpoint)
|
|
33
33
|
return;
|
|
34
|
-
const
|
|
35
|
-
if (
|
|
36
|
-
return
|
|
37
|
-
const
|
|
34
|
+
const l = s();
|
|
35
|
+
if (r && a - 30 > l)
|
|
36
|
+
return r;
|
|
37
|
+
const i = await n(e.sessionEndpoint, {
|
|
38
38
|
method: "GET",
|
|
39
|
-
headers: await
|
|
39
|
+
headers: await p()
|
|
40
40
|
});
|
|
41
|
-
if (!
|
|
42
|
-
throw new Error(await
|
|
43
|
-
const
|
|
44
|
-
return
|
|
41
|
+
if (!i.ok)
|
|
42
|
+
throw new Error(await P(i));
|
|
43
|
+
const c = await i.json();
|
|
44
|
+
return r = c.token, a = c.expires_at, r;
|
|
45
45
|
}
|
|
46
|
-
async function
|
|
47
|
-
const
|
|
48
|
-
return e.challengeTokenProvider && (
|
|
46
|
+
async function p() {
|
|
47
|
+
const l = {};
|
|
48
|
+
return e.challengeTokenProvider && (l["X-Seer-Challenge-Token"] = await e.challengeTokenProvider()), l;
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
|
-
function
|
|
52
|
-
var t,
|
|
51
|
+
function j(e) {
|
|
52
|
+
var t, s, r;
|
|
53
53
|
const n = (t = e.choices) == null ? void 0 : t[0];
|
|
54
54
|
return {
|
|
55
|
-
content: ((
|
|
55
|
+
content: ((s = n == null ? void 0 : n.message) == null ? void 0 : s.content) ?? ((r = n == null ? void 0 : n.delta) == null ? void 0 : r.content) ?? "",
|
|
56
56
|
conversationId: e.conversation_id,
|
|
57
57
|
citations: e.citations ?? [],
|
|
58
58
|
handoffRequested: e.handoff_requested ?? !1,
|
|
59
59
|
finishReason: n == null ? void 0 : n.finish_reason
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
|
-
async function
|
|
63
|
-
var
|
|
62
|
+
async function G(e, n) {
|
|
63
|
+
var c, o, m;
|
|
64
64
|
if (!e.body)
|
|
65
|
-
return
|
|
66
|
-
const t = e.body.getReader(),
|
|
67
|
-
let
|
|
65
|
+
return j({});
|
|
66
|
+
const t = e.body.getReader(), s = new TextDecoder();
|
|
67
|
+
let r = "", a = "", v, p = [], l = !1, i;
|
|
68
68
|
for (; ; ) {
|
|
69
|
-
const { done:
|
|
70
|
-
if (
|
|
69
|
+
const { done: k, value: w } = await t.read();
|
|
70
|
+
if (k)
|
|
71
71
|
break;
|
|
72
|
-
|
|
73
|
-
const
|
|
72
|
+
r += s.decode(w, { stream: !0 });
|
|
73
|
+
const x = r.split(`
|
|
74
74
|
|
|
75
75
|
`);
|
|
76
|
-
|
|
77
|
-
for (const
|
|
78
|
-
const
|
|
79
|
-
if (!
|
|
76
|
+
r = x.pop() ?? "";
|
|
77
|
+
for (const u of x) {
|
|
78
|
+
const E = H(u);
|
|
79
|
+
if (!E || E === "[DONE]")
|
|
80
80
|
continue;
|
|
81
|
-
const
|
|
82
|
-
|
|
81
|
+
const b = JSON.parse(E), d = (c = b.choices) == null ? void 0 : c[0], S = ((o = d == null ? void 0 : d.delta) == null ? void 0 : o.content) ?? ((m = d == null ? void 0 : d.message) == null ? void 0 : m.content) ?? "";
|
|
82
|
+
S && (a += S, n == null || n(S)), v = b.conversation_id ?? v, p = b.citations ?? p, l = b.handoff_requested ?? l, i = (d == null ? void 0 : d.finish_reason) ?? i;
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
return {
|
|
86
|
-
content:
|
|
87
|
-
conversationId:
|
|
88
|
-
citations:
|
|
89
|
-
handoffRequested:
|
|
90
|
-
finishReason:
|
|
86
|
+
content: a,
|
|
87
|
+
conversationId: v,
|
|
88
|
+
citations: p,
|
|
89
|
+
handoffRequested: l,
|
|
90
|
+
finishReason: i
|
|
91
91
|
};
|
|
92
92
|
}
|
|
93
|
-
function
|
|
93
|
+
function H(e) {
|
|
94
94
|
const n = e.split(`
|
|
95
95
|
`).map((t) => t.trim()).filter((t) => t.startsWith("data:")).map((t) => t.slice(5).trim());
|
|
96
96
|
return n.length === 0 ? null : n.join(`
|
|
97
97
|
`);
|
|
98
98
|
}
|
|
99
|
-
async function
|
|
99
|
+
async function P(e) {
|
|
100
100
|
let n = e.statusText || "unknown error";
|
|
101
101
|
try {
|
|
102
102
|
const t = await e.json();
|
|
@@ -107,111 +107,142 @@ async function j(e) {
|
|
|
107
107
|
}
|
|
108
108
|
return `seer chat request failed with status ${e.status}: ${n}`;
|
|
109
109
|
}
|
|
110
|
-
const
|
|
111
|
-
function
|
|
112
|
-
return /标签|箱唛/.test(e) ? "点击下载箱唛" : /入库单|交接单/.test(e) ? "点击下载入库单" : /面单/.test(e) ? "点击下载面单" : /截图/.test(e) ? "点击查看报价截图" : /下载链接|labelUrl|下载/.test(e) ? "点击下载" : /链接/.test(e) ? "点击查看" : null;
|
|
113
|
-
}
|
|
114
|
-
function G(e) {
|
|
110
|
+
const O = /https?:\/\/[^\s)]+/g, J = /\.(png|jpe?g|gif|webp|bmp|svg)$/i, W = "单价\\s*\\d[\\d.]*\\s*[A-Za-z]+\\/kg", Y = "按当前信息为您筛选出[^\\n:]*推荐方案[^\\n:]*:", Z = "方案PK|时效最快|价格最低", $ = new RegExp(`(${W})|(${Y})|(${Z})`, "g");
|
|
111
|
+
function L(e) {
|
|
115
112
|
const n = [];
|
|
116
|
-
|
|
117
|
-
let t = 0,
|
|
118
|
-
for (; (
|
|
119
|
-
|
|
120
|
-
r
|
|
121
|
-
|
|
122
|
-
`, r - 1) + 1, o = J(e.slice(d, r)) ?? l;
|
|
123
|
-
n.push({ kind: "link", href: l, label: o }), t = r + l.length;
|
|
113
|
+
$.lastIndex = 0;
|
|
114
|
+
let t = 0, s;
|
|
115
|
+
for (; (s = $.exec(e)) !== null; ) {
|
|
116
|
+
s.index > t && n.push({ kind: "text", value: e.slice(t, s.index) });
|
|
117
|
+
const r = s[0];
|
|
118
|
+
n.push(s[1] ? { kind: "price", value: r } : { kind: "strong", value: r }), t = s.index + r.length;
|
|
124
119
|
}
|
|
125
120
|
return t < e.length && n.push({ kind: "text", value: e.slice(t) }), n;
|
|
126
121
|
}
|
|
127
|
-
|
|
122
|
+
const Q = /标签|箱唛|唛头|入库单|交接单|入仓单|面单|下载/;
|
|
123
|
+
function ee(e, n) {
|
|
124
|
+
if (/方案|截图|报价图|效果图|示意图|图片/.test(n))
|
|
125
|
+
return !0;
|
|
126
|
+
if (Q.test(n))
|
|
127
|
+
return !1;
|
|
128
|
+
const t = e.split(/[?#]/)[0];
|
|
129
|
+
return J.test(t);
|
|
130
|
+
}
|
|
131
|
+
function te(e) {
|
|
132
|
+
return /方案|报价|截图|PK/.test(e) ? "方案PK" : "图片";
|
|
133
|
+
}
|
|
134
|
+
function ne(e) {
|
|
135
|
+
return /标签|箱唛/.test(e) ? "点击下载箱唛" : /入库单|交接单/.test(e) ? "点击下载入库单" : /面单/.test(e) ? "点击下载面单" : /截图|方案/.test(e) ? "点击查看方案PK" : /下载链接|labelUrl|下载/.test(e) ? "点击下载" : /链接/.test(e) ? "点击查看" : null;
|
|
136
|
+
}
|
|
137
|
+
function se(e) {
|
|
138
|
+
const n = [];
|
|
139
|
+
O.lastIndex = 0;
|
|
140
|
+
let t = 0, s;
|
|
141
|
+
for (; (s = O.exec(e)) !== null; ) {
|
|
142
|
+
const r = s[0], a = s.index, v = e.lastIndexOf(`
|
|
143
|
+
`, a - 1) + 1, p = e.slice(v, a), l = ee(r, p);
|
|
144
|
+
if (a > t) {
|
|
145
|
+
let i = e.slice(t, a);
|
|
146
|
+
l && (i = i.replace(/链接([::])\s*$/, "$1")), n.push(...L(i));
|
|
147
|
+
}
|
|
148
|
+
l ? n.push({ kind: "image", href: r, alt: te(p) }) : n.push({ kind: "link", href: r, label: ne(p) ?? r }), t = a + r.length;
|
|
149
|
+
}
|
|
150
|
+
return t < e.length && n.push(...L(e.slice(t))), n;
|
|
151
|
+
}
|
|
152
|
+
function ae(e) {
|
|
128
153
|
return e.split(`
|
|
129
|
-
`).map((n) =>
|
|
154
|
+
`).map((n) => se(n));
|
|
130
155
|
}
|
|
131
|
-
const
|
|
156
|
+
const N = Symbol("seer-chat-options"), Ie = {
|
|
132
157
|
install(e, n) {
|
|
133
|
-
e.provide(
|
|
158
|
+
e.provide(N, n);
|
|
134
159
|
}
|
|
135
160
|
};
|
|
136
|
-
function
|
|
137
|
-
const t = { ...
|
|
161
|
+
function oe(e = {}) {
|
|
162
|
+
const t = { ...K() ? D(N, void 0) : void 0, ...e };
|
|
138
163
|
if (!t.endpoint)
|
|
139
164
|
throw new Error("Seer chat endpoint is required. Pass it to app.use() or useSeerChat().");
|
|
140
|
-
const
|
|
165
|
+
const s = {
|
|
141
166
|
endpoint: t.endpoint,
|
|
142
167
|
sessionEndpoint: t.sessionEndpoint,
|
|
143
168
|
challengeTokenProvider: t.challengeTokenProvider,
|
|
144
169
|
model: t.model,
|
|
145
170
|
fetcher: t.fetcher
|
|
146
|
-
},
|
|
147
|
-
let
|
|
148
|
-
async function
|
|
149
|
-
const
|
|
150
|
-
if (!
|
|
171
|
+
}, r = X(s), a = y([]), v = y(!1), p = y(null), l = y(), i = y([]), c = y(!1);
|
|
172
|
+
let o = null;
|
|
173
|
+
async function m(x) {
|
|
174
|
+
const u = x.trim();
|
|
175
|
+
if (!u || v.value)
|
|
151
176
|
return;
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
const
|
|
155
|
-
t.stream && (
|
|
177
|
+
const E = { role: "user", content: u };
|
|
178
|
+
a.value = [...a.value, E], v.value = !0, p.value = null, o = new AbortController();
|
|
179
|
+
const b = { role: "assistant", content: "" };
|
|
180
|
+
t.stream && (a.value = [...a.value, b]);
|
|
156
181
|
try {
|
|
157
|
-
const
|
|
182
|
+
const d = await r.chat(
|
|
158
183
|
{
|
|
159
|
-
messages:
|
|
184
|
+
messages: a.value.filter((S) => S.content),
|
|
160
185
|
stream: t.stream ?? !1,
|
|
161
|
-
conversationId:
|
|
186
|
+
conversationId: l.value
|
|
162
187
|
},
|
|
163
188
|
{
|
|
164
|
-
signal:
|
|
165
|
-
onDelta(
|
|
166
|
-
|
|
189
|
+
signal: o.signal,
|
|
190
|
+
onDelta(S) {
|
|
191
|
+
b.content += S, a.value = [...a.value];
|
|
167
192
|
}
|
|
168
193
|
}
|
|
169
194
|
);
|
|
170
|
-
t.stream || (
|
|
171
|
-
} catch (
|
|
172
|
-
|
|
195
|
+
t.stream || (a.value = [...a.value, { role: "assistant", content: d.content }]), l.value = d.conversationId, i.value = d.citations, c.value = d.handoffRequested;
|
|
196
|
+
} catch (d) {
|
|
197
|
+
d.name !== "AbortError" && (p.value = d instanceof Error ? d.message : String(d));
|
|
173
198
|
} finally {
|
|
174
|
-
|
|
199
|
+
v.value = !1, o = null;
|
|
175
200
|
}
|
|
176
201
|
}
|
|
177
|
-
function
|
|
178
|
-
|
|
202
|
+
function k() {
|
|
203
|
+
a.value = [], p.value = null, l.value = void 0, i.value = [], c.value = !1;
|
|
179
204
|
}
|
|
180
|
-
function
|
|
181
|
-
|
|
205
|
+
function w() {
|
|
206
|
+
o == null || o.abort();
|
|
182
207
|
}
|
|
183
208
|
return {
|
|
184
|
-
messages:
|
|
185
|
-
loading:
|
|
186
|
-
error:
|
|
187
|
-
conversationId:
|
|
188
|
-
citations:
|
|
189
|
-
handoffRequested:
|
|
190
|
-
send:
|
|
191
|
-
reset:
|
|
192
|
-
abort:
|
|
209
|
+
messages: a,
|
|
210
|
+
loading: v,
|
|
211
|
+
error: p,
|
|
212
|
+
conversationId: l,
|
|
213
|
+
citations: i,
|
|
214
|
+
handoffRequested: c,
|
|
215
|
+
send: m,
|
|
216
|
+
reset: k,
|
|
217
|
+
abort: w
|
|
193
218
|
};
|
|
194
219
|
}
|
|
195
|
-
const
|
|
220
|
+
const re = {
|
|
196
221
|
class: "seer-chat",
|
|
197
222
|
"aria-label": "多发货 AI 客服聊天"
|
|
198
|
-
},
|
|
223
|
+
}, le = { class: "seer-chat__header" }, ie = {
|
|
199
224
|
class: "seer-chat__messages",
|
|
200
225
|
"aria-live": "polite"
|
|
201
|
-
},
|
|
226
|
+
}, ce = {
|
|
202
227
|
key: 0,
|
|
203
228
|
class: "seer-chat__empty"
|
|
204
|
-
},
|
|
229
|
+
}, ue = { class: "seer-chat__role" }, de = { class: "seer-chat__body" }, fe = ["href"], he = ["aria-label", "onClick"], _e = ["src", "alt"], ve = {
|
|
230
|
+
key: 2,
|
|
231
|
+
class: "seer-chat__strong"
|
|
232
|
+
}, pe = {
|
|
233
|
+
key: 3,
|
|
234
|
+
class: "seer-chat__price"
|
|
235
|
+
}, me = { key: 4 }, ge = {
|
|
205
236
|
key: 0,
|
|
206
237
|
class: "seer-chat__status"
|
|
207
|
-
},
|
|
238
|
+
}, ke = {
|
|
208
239
|
key: 1,
|
|
209
240
|
class: "seer-chat__error",
|
|
210
241
|
role: "alert"
|
|
211
|
-
},
|
|
242
|
+
}, be = {
|
|
212
243
|
key: 2,
|
|
213
244
|
class: "seer-chat__handoff"
|
|
214
|
-
},
|
|
245
|
+
}, ye = ["placeholder", "disabled", "onKeydown"], we = { class: "seer-chat__composer-footer" }, Ee = ["disabled"], Se = ["aria-label"], Ce = ["src", "alt"], xe = /* @__PURE__ */ U({
|
|
215
246
|
__name: "SeerChat",
|
|
216
247
|
props: {
|
|
217
248
|
endpoint: {},
|
|
@@ -222,110 +253,155 @@ const X = {
|
|
|
222
253
|
placeholder: { default: "输入你的问题,例如:美国海派怎么报价?" }
|
|
223
254
|
},
|
|
224
255
|
setup(e) {
|
|
225
|
-
const n = e, t =
|
|
256
|
+
const n = e, t = y(""), s = oe({
|
|
226
257
|
endpoint: n.endpoint,
|
|
227
258
|
model: n.model,
|
|
228
259
|
stream: n.stream,
|
|
229
260
|
fetcher: n.fetcher
|
|
230
|
-
}),
|
|
231
|
-
() => t.value.trim().length > 0 && !
|
|
232
|
-
);
|
|
233
|
-
|
|
234
|
-
|
|
261
|
+
}), r = B(
|
|
262
|
+
() => t.value.trim().length > 0 && !s.loading.value
|
|
263
|
+
), a = y(null);
|
|
264
|
+
function v(c) {
|
|
265
|
+
c.key === "Escape" && l();
|
|
266
|
+
}
|
|
267
|
+
function p(c, o) {
|
|
268
|
+
a.value = { src: c, alt: o }, window.addEventListener("keydown", v);
|
|
269
|
+
}
|
|
270
|
+
function l() {
|
|
271
|
+
a.value = null, window.removeEventListener("keydown", v);
|
|
272
|
+
}
|
|
273
|
+
M(() => {
|
|
274
|
+
window.removeEventListener("keydown", v);
|
|
275
|
+
});
|
|
276
|
+
async function i() {
|
|
277
|
+
if (!r.value)
|
|
235
278
|
return;
|
|
236
|
-
const
|
|
237
|
-
t.value = "", await
|
|
279
|
+
const c = t.value;
|
|
280
|
+
t.value = "", await s.send(c);
|
|
238
281
|
}
|
|
239
|
-
return (
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
o[3] || (o[3] =
|
|
282
|
+
return (c, o) => (h(), _("section", re, [
|
|
283
|
+
f("header", le, [
|
|
284
|
+
f("div", null, [
|
|
285
|
+
f("h2", null, C(e.title), 1),
|
|
286
|
+
o[3] || (o[3] = f("p", null, "可咨询渠道报价、时效、下单资料、入仓和售后问题。", -1))
|
|
244
287
|
]),
|
|
245
|
-
|
|
288
|
+
f("button", {
|
|
246
289
|
type: "button",
|
|
247
290
|
class: "seer-chat__clear-button",
|
|
248
|
-
onClick: o[0] || (o[0] = (
|
|
291
|
+
onClick: o[0] || (o[0] = (m) => g(s).reset())
|
|
249
292
|
}, " 清空对话 ")
|
|
250
293
|
]),
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
(
|
|
254
|
-
key: `${
|
|
255
|
-
class:
|
|
294
|
+
f("div", ie, [
|
|
295
|
+
g(s).messages.value.length === 0 ? (h(), _("p", ce, " 直接输入问题即可,复杂查单或赔付问题会提示转人工。 ")) : T("", !0),
|
|
296
|
+
(h(!0), _(R, null, I(g(s).messages.value, (m, k) => (h(), _("article", {
|
|
297
|
+
key: `${m.role}-${k}`,
|
|
298
|
+
class: q(["seer-chat__message", `seer-chat__message--${m.role}`])
|
|
256
299
|
}, [
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
(
|
|
260
|
-
key:
|
|
300
|
+
f("span", ue, C(m.role === "user" ? "你" : "AI 客服"), 1),
|
|
301
|
+
f("div", de, [
|
|
302
|
+
(h(!0), _(R, null, I(g(ae)(m.content), (w, x) => (h(), _("p", {
|
|
303
|
+
key: x,
|
|
261
304
|
class: "seer-chat__line"
|
|
262
305
|
}, [
|
|
263
|
-
(
|
|
264
|
-
|
|
306
|
+
(h(!0), _(R, null, I(w, (u, E) => (h(), _(R, { key: E }, [
|
|
307
|
+
u.kind === "link" ? (h(), _("a", {
|
|
265
308
|
key: 0,
|
|
266
309
|
class: "seer-chat__link",
|
|
267
|
-
href:
|
|
310
|
+
href: u.href,
|
|
268
311
|
target: "_blank",
|
|
269
312
|
rel: "noopener noreferrer"
|
|
270
|
-
}, C(
|
|
313
|
+
}, C(u.label), 9, fe)) : u.kind === "image" ? (h(), _("button", {
|
|
314
|
+
key: 1,
|
|
315
|
+
type: "button",
|
|
316
|
+
class: "seer-chat__image-button",
|
|
317
|
+
"aria-label": `放大查看${u.alt}`,
|
|
318
|
+
onClick: (b) => p(u.href, u.alt)
|
|
319
|
+
}, [
|
|
320
|
+
f("img", {
|
|
321
|
+
class: "seer-chat__image",
|
|
322
|
+
src: u.href,
|
|
323
|
+
alt: u.alt,
|
|
324
|
+
loading: "lazy"
|
|
325
|
+
}, null, 8, _e)
|
|
326
|
+
], 8, he)) : u.kind === "strong" ? (h(), _("strong", ve, C(u.value), 1)) : u.kind === "price" ? (h(), _("span", pe, C(u.value), 1)) : (h(), _("span", me, C(u.value), 1))
|
|
271
327
|
], 64))), 128))
|
|
272
328
|
]))), 128))
|
|
273
329
|
])
|
|
274
330
|
], 2))), 128))
|
|
275
331
|
]),
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
332
|
+
g(s).loading.value ? (h(), _("p", ge, "正在回复...")) : T("", !0),
|
|
333
|
+
g(s).error.value ? (h(), _("p", ke, C(g(s).error.value), 1)) : T("", !0),
|
|
334
|
+
g(s).handoffRequested.value ? (h(), _("p", be, " 建议转人工:请留下联系方式或等待客服接入。 ")) : T("", !0),
|
|
335
|
+
f("form", {
|
|
280
336
|
class: "seer-chat__form",
|
|
281
|
-
onSubmit:
|
|
337
|
+
onSubmit: A(i, ["prevent"])
|
|
282
338
|
}, [
|
|
283
|
-
o[6] || (o[6] =
|
|
339
|
+
o[6] || (o[6] = f("label", {
|
|
284
340
|
class: "seer-chat__label",
|
|
285
341
|
for: "seer-chat-input"
|
|
286
342
|
}, "问题", -1)),
|
|
287
|
-
|
|
343
|
+
z(f("textarea", {
|
|
288
344
|
id: "seer-chat-input",
|
|
289
|
-
"onUpdate:modelValue": o[1] || (o[1] = (
|
|
345
|
+
"onUpdate:modelValue": o[1] || (o[1] = (m) => t.value = m),
|
|
290
346
|
placeholder: e.placeholder,
|
|
291
|
-
disabled:
|
|
347
|
+
disabled: g(s).loading.value,
|
|
292
348
|
rows: "3",
|
|
293
|
-
onKeydown:
|
|
294
|
-
}, null, 40,
|
|
295
|
-
[
|
|
349
|
+
onKeydown: F(A(i, ["exact", "prevent"]), ["enter"])
|
|
350
|
+
}, null, 40, ye), [
|
|
351
|
+
[V, t.value]
|
|
296
352
|
]),
|
|
297
|
-
|
|
298
|
-
o[5] || (o[5] =
|
|
299
|
-
|
|
353
|
+
f("div", we, [
|
|
354
|
+
o[5] || (o[5] = f("span", { class: "seer-chat__hint" }, "Enter 发送 · Shift+Enter 换行", -1)),
|
|
355
|
+
g(s).loading.value ? (h(), _("button", {
|
|
300
356
|
key: 0,
|
|
301
357
|
type: "button",
|
|
302
358
|
class: "seer-chat__stop-button",
|
|
303
|
-
onClick: o[2] || (o[2] = (
|
|
304
|
-
}, " 停止 ")) :
|
|
305
|
-
|
|
359
|
+
onClick: o[2] || (o[2] = (m) => g(s).abort())
|
|
360
|
+
}, " 停止 ")) : T("", !0),
|
|
361
|
+
f("button", {
|
|
306
362
|
class: "seer-chat__send-button",
|
|
307
363
|
type: "submit",
|
|
308
|
-
disabled: !
|
|
364
|
+
disabled: !r.value
|
|
309
365
|
}, [...o[4] || (o[4] = [
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
])], 8,
|
|
366
|
+
f("span", null, "发送", -1),
|
|
367
|
+
f("span", { "aria-hidden": "true" }, "↵", -1)
|
|
368
|
+
])], 8, Ee)
|
|
313
369
|
])
|
|
314
|
-
], 32)
|
|
370
|
+
], 32),
|
|
371
|
+
a.value ? (h(), _("div", {
|
|
372
|
+
key: 3,
|
|
373
|
+
class: "seer-chat__lightbox",
|
|
374
|
+
role: "dialog",
|
|
375
|
+
"aria-modal": "true",
|
|
376
|
+
"aria-label": a.value.alt,
|
|
377
|
+
onClick: l
|
|
378
|
+
}, [
|
|
379
|
+
f("button", {
|
|
380
|
+
type: "button",
|
|
381
|
+
class: "seer-chat__lightbox-close",
|
|
382
|
+
"aria-label": "关闭",
|
|
383
|
+
onClick: l
|
|
384
|
+
}, " × "),
|
|
385
|
+
f("img", {
|
|
386
|
+
class: "seer-chat__lightbox-image",
|
|
387
|
+
src: a.value.src,
|
|
388
|
+
alt: a.value.alt
|
|
389
|
+
}, null, 8, Ce)
|
|
390
|
+
], 8, Se)) : T("", !0)
|
|
315
391
|
]));
|
|
316
392
|
}
|
|
317
|
-
}),
|
|
393
|
+
}), Te = (e, n) => {
|
|
318
394
|
const t = e.__vccOpts || e;
|
|
319
|
-
for (const [
|
|
320
|
-
t[
|
|
395
|
+
for (const [s, r] of n)
|
|
396
|
+
t[s] = r;
|
|
321
397
|
return t;
|
|
322
|
-
},
|
|
398
|
+
}, Ae = /* @__PURE__ */ Te(xe, [["__scopeId", "data-v-dc651545"]]);
|
|
323
399
|
export {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
400
|
+
Ae as SeerChat,
|
|
401
|
+
Ie as SeerChatPlugin,
|
|
402
|
+
X as createSeerClient,
|
|
403
|
+
ne as linkAnchorLabel,
|
|
404
|
+
ae as toContentLines,
|
|
405
|
+
se as toContentSegments,
|
|
406
|
+
oe as useSeerChat
|
|
331
407
|
};
|