@siact/sime-x-vue 0.0.17 → 0.0.19
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/sime-x-vue.mjs +87 -25
- package/dist/sime-x-vue.mjs.map +1 -1
- package/dist/sime-x-vue.umd.js +87 -25
- package/dist/sime-x-vue.umd.js.map +1 -1
- package/dist/style.css +109 -109
- package/package.json +1 -1
- package/types/components/sime-provider.vue.d.ts +2 -0
- package/types/types.d.ts +6 -0
package/dist/sime-x-vue.umd.js
CHANGED
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
const _hoisted_10$2 = { class: "ai-chat__messages-inner" };
|
|
108
108
|
const _hoisted_11$2 = { class: "ai-chat__message-content" };
|
|
109
109
|
const _hoisted_12$2 = ["innerHTML"];
|
|
110
|
-
const _hoisted_13$
|
|
110
|
+
const _hoisted_13$1 = {
|
|
111
111
|
key: 1,
|
|
112
112
|
class: "ai-chat__reasoning"
|
|
113
113
|
};
|
|
@@ -470,7 +470,7 @@
|
|
|
470
470
|
innerHTML: renderMarkdown(part.text)
|
|
471
471
|
}, null, 8, _hoisted_12$2)
|
|
472
472
|
])
|
|
473
|
-
], 2)) : part.type === "reasoning" ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_13$
|
|
473
|
+
], 2)) : part.type === "reasoning" ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_13$1, [
|
|
474
474
|
vue.createElementVNode("button", {
|
|
475
475
|
class: "ai-chat__reasoning-trigger",
|
|
476
476
|
onClick: ($event) => toggleReasoning(message.id)
|
|
@@ -1465,7 +1465,7 @@
|
|
|
1465
1465
|
};
|
|
1466
1466
|
const _hoisted_11$1 = { class: "input-bar" };
|
|
1467
1467
|
const _hoisted_12$1 = ["disabled"];
|
|
1468
|
-
const _hoisted_13
|
|
1468
|
+
const _hoisted_13 = ["disabled"];
|
|
1469
1469
|
const _hoisted_14 = {
|
|
1470
1470
|
key: 0,
|
|
1471
1471
|
class: "btn-spinner",
|
|
@@ -1512,6 +1512,12 @@
|
|
|
1512
1512
|
scrollToBottom: () => {
|
|
1513
1513
|
}
|
|
1514
1514
|
};
|
|
1515
|
+
const test = () => {
|
|
1516
|
+
aiChatbotX.invokeText("你好");
|
|
1517
|
+
};
|
|
1518
|
+
const test1 = () => {
|
|
1519
|
+
aiChatbotX.abortInvoke();
|
|
1520
|
+
};
|
|
1515
1521
|
const endpoint = `/sime/proxy/organizations/${aiChatbotX.organizationId()}/agents/${props.agentId}/stream-invoke`;
|
|
1516
1522
|
const agent = useAgentInvoke({
|
|
1517
1523
|
endpoint,
|
|
@@ -1550,6 +1556,8 @@
|
|
|
1550
1556
|
class: "command-test",
|
|
1551
1557
|
"data-theme": currentTheme$1
|
|
1552
1558
|
}, [
|
|
1559
|
+
vue.createElementVNode("button", { onClick: test }, "测试"),
|
|
1560
|
+
vue.createElementVNode("button", { onClick: test1 }, "测试1"),
|
|
1553
1561
|
vue.createVNode(vue.Transition, { name: "bubble-fade" }, {
|
|
1554
1562
|
default: vue.withCtx(() => [
|
|
1555
1563
|
vue.unref(showBubble) ? (vue.openBlock(), vue.createElementBlock("div", {
|
|
@@ -1664,14 +1672,14 @@
|
|
|
1664
1672
|
"stroke-linejoin": "round"
|
|
1665
1673
|
}, null, -1)
|
|
1666
1674
|
])]))
|
|
1667
|
-
], 8, _hoisted_13
|
|
1675
|
+
], 8, _hoisted_13)
|
|
1668
1676
|
])
|
|
1669
1677
|
]);
|
|
1670
1678
|
};
|
|
1671
1679
|
}
|
|
1672
1680
|
});
|
|
1673
1681
|
|
|
1674
|
-
const commandTest = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-
|
|
1682
|
+
const commandTest = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-93ed98f5"]]);
|
|
1675
1683
|
|
|
1676
1684
|
class CommandManager {
|
|
1677
1685
|
commands = /* @__PURE__ */ new Map();
|
|
@@ -1732,7 +1740,8 @@
|
|
|
1732
1740
|
__name: "sime-provider",
|
|
1733
1741
|
props: {
|
|
1734
1742
|
appToken: {},
|
|
1735
|
-
organizationId: {}
|
|
1743
|
+
organizationId: {},
|
|
1744
|
+
projectId: {}
|
|
1736
1745
|
},
|
|
1737
1746
|
setup(__props) {
|
|
1738
1747
|
const props = __props;
|
|
@@ -1743,6 +1752,9 @@
|
|
|
1743
1752
|
});
|
|
1744
1753
|
const stopBroadcastRef = vue.shallowRef(async () => {
|
|
1745
1754
|
});
|
|
1755
|
+
const voiceAssistantRef = vue.shallowRef(
|
|
1756
|
+
null
|
|
1757
|
+
);
|
|
1746
1758
|
vue.provide(AiChatbotXKey, {
|
|
1747
1759
|
appToken: () => props.appToken,
|
|
1748
1760
|
organizationId: () => props.organizationId,
|
|
@@ -1754,6 +1766,9 @@
|
|
|
1754
1766
|
if (methods.start) startListeningRef.value = methods.start;
|
|
1755
1767
|
if (methods.stop) stopListeningRef.value = methods.stop;
|
|
1756
1768
|
},
|
|
1769
|
+
registerVoiceAssistant: (methods) => {
|
|
1770
|
+
voiceAssistantRef.value = methods;
|
|
1771
|
+
},
|
|
1757
1772
|
getCommads: async () => commandManager.value.getCommands(),
|
|
1758
1773
|
registerCommand: (cmd) => {
|
|
1759
1774
|
commandManager.value.registerCommand(cmd);
|
|
@@ -1763,6 +1778,12 @@
|
|
|
1763
1778
|
},
|
|
1764
1779
|
async executeCommand(commandName, args = []) {
|
|
1765
1780
|
return await commandManager.value.executeCommand(commandName, args);
|
|
1781
|
+
},
|
|
1782
|
+
invokeText: async (text) => {
|
|
1783
|
+
voiceAssistantRef.value?.agentInvoke(text);
|
|
1784
|
+
},
|
|
1785
|
+
abortInvoke: () => {
|
|
1786
|
+
voiceAssistantRef.value?.agentAbort();
|
|
1766
1787
|
}
|
|
1767
1788
|
});
|
|
1768
1789
|
return (_ctx, _cache) => {
|
|
@@ -1778,8 +1799,47 @@
|
|
|
1778
1799
|
let initPromise = null;
|
|
1779
1800
|
let audioCtx = null;
|
|
1780
1801
|
let sentenceBuffer = "";
|
|
1781
|
-
const
|
|
1782
|
-
const
|
|
1802
|
+
const SENTENCE_DELIMITERS = /[。!?;\n!?;]/;
|
|
1803
|
+
const LEADING_WEAK_PUNCTUATION = /^[\s,、;:,.!?。]+/;
|
|
1804
|
+
const TRAILING_SENTENCE_PUNCTUATION = /[。!?.!?;;]$/;
|
|
1805
|
+
const findSentenceBoundary = (text) => {
|
|
1806
|
+
for (let i = 0; i < text.length; i++) {
|
|
1807
|
+
const char = text[i];
|
|
1808
|
+
if (SENTENCE_DELIMITERS.test(char)) {
|
|
1809
|
+
return i;
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
return -1;
|
|
1813
|
+
};
|
|
1814
|
+
const normalizeNumbers = (text) => {
|
|
1815
|
+
return text.replace(/(-?\d[\d,]*\.?\d*)\s*%/g, (_, num) => {
|
|
1816
|
+
const cleanNum = num.replace(/,/g, "");
|
|
1817
|
+
const n = parseFloat(cleanNum);
|
|
1818
|
+
const spoken = cleanNum.replace(".", "点");
|
|
1819
|
+
if (n < 0) return `负百分之${spoken.replace("-", "")}`;
|
|
1820
|
+
return `百分之${spoken}`;
|
|
1821
|
+
}).replace(/(-?\d[\d,]*)\.(\d+)/g, (_, intPart, decPart) => {
|
|
1822
|
+
const cleanInt = intPart.replace(/,/g, "");
|
|
1823
|
+
if (cleanInt.startsWith("-")) {
|
|
1824
|
+
return `负${cleanInt.slice(1)}点${decPart}`;
|
|
1825
|
+
}
|
|
1826
|
+
return `${cleanInt}点${decPart}`;
|
|
1827
|
+
}).replace(/-(\d)/g, "负$1");
|
|
1828
|
+
};
|
|
1829
|
+
const stripMarkdown = (text) => {
|
|
1830
|
+
let result = text.replace(/```[\s\S]*?```/g, "").replace(/\|[^\n]*\|/g, "").replace(/#{1,6}\s*/g, "").replace(/\*\*(.*?)\*\*/g, "$1").replace(/\*(.*?)\*/g, "$1").replace(/`([^`]*)`/g, "$1").replace(/\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/^[-*+]\s+/gm, "").replace(/^>\s+/gm, "");
|
|
1831
|
+
result = normalizeNumbers(result);
|
|
1832
|
+
result = result.replace(/\s*\+\s*(?=\d)/g, "加").replace(/\s*\+\s*/g, "加").replace(/\s*-\s*(?=\d)/g, "减").replace(/\s*-\s*/g, "减").replace(/\s*×\s*/g, "乘").replace(/\s*÷\s*/g, "除").replace(/\s*=\s*/g, "等于").replace(/\n{2,}/g, "。").replace(/\n/g, ",").trim();
|
|
1833
|
+
return result;
|
|
1834
|
+
};
|
|
1835
|
+
const normalizeSpeakText = (text, options) => {
|
|
1836
|
+
const clean = stripMarkdown(text).replace(LEADING_WEAK_PUNCTUATION, "").trim();
|
|
1837
|
+
if (!clean) return "";
|
|
1838
|
+
if (options?.isFinalChunk && !TRAILING_SENTENCE_PUNCTUATION.test(clean)) {
|
|
1839
|
+
return `${clean}。`;
|
|
1840
|
+
}
|
|
1841
|
+
return clean;
|
|
1842
|
+
};
|
|
1783
1843
|
const warmUpAudio = () => {
|
|
1784
1844
|
if (!audioCtx || audioCtx.state === "closed") {
|
|
1785
1845
|
try {
|
|
@@ -1848,7 +1908,7 @@
|
|
|
1848
1908
|
return initPromise;
|
|
1849
1909
|
};
|
|
1850
1910
|
const speak = async (text) => {
|
|
1851
|
-
const clean =
|
|
1911
|
+
const clean = normalizeSpeakText(text);
|
|
1852
1912
|
if (!clean.trim()) return;
|
|
1853
1913
|
hasPendingAudio.value = true;
|
|
1854
1914
|
const tts = await ensureInstance();
|
|
@@ -1862,17 +1922,20 @@
|
|
|
1862
1922
|
const feed = (delta) => {
|
|
1863
1923
|
sentenceBuffer += delta;
|
|
1864
1924
|
while (true) {
|
|
1865
|
-
const
|
|
1866
|
-
if (
|
|
1867
|
-
const sentence = sentenceBuffer.slice(0,
|
|
1868
|
-
sentenceBuffer = sentenceBuffer.slice(
|
|
1925
|
+
const boundaryIndex = findSentenceBoundary(sentenceBuffer);
|
|
1926
|
+
if (boundaryIndex === -1) break;
|
|
1927
|
+
const sentence = sentenceBuffer.slice(0, boundaryIndex + 1).trim();
|
|
1928
|
+
sentenceBuffer = sentenceBuffer.slice(boundaryIndex + 1);
|
|
1869
1929
|
if (sentence.length > 0) speak(sentence);
|
|
1870
1930
|
}
|
|
1871
1931
|
};
|
|
1872
1932
|
const flush = () => {
|
|
1873
1933
|
const remaining = sentenceBuffer.trim();
|
|
1874
1934
|
sentenceBuffer = "";
|
|
1875
|
-
if (remaining.length > 0)
|
|
1935
|
+
if (remaining.length > 0) {
|
|
1936
|
+
const clean = normalizeSpeakText(remaining, { isFinalChunk: true });
|
|
1937
|
+
if (clean) void speak(clean);
|
|
1938
|
+
}
|
|
1876
1939
|
};
|
|
1877
1940
|
const stop = () => {
|
|
1878
1941
|
sentenceBuffer = "";
|
|
@@ -2188,12 +2251,8 @@
|
|
|
2188
2251
|
key: 2,
|
|
2189
2252
|
class: "agent-text"
|
|
2190
2253
|
};
|
|
2191
|
-
const _hoisted_11 = {
|
|
2192
|
-
|
|
2193
|
-
class: "status-pill"
|
|
2194
|
-
};
|
|
2195
|
-
const _hoisted_12 = { class: "fab-avatar-wrapper" };
|
|
2196
|
-
const _hoisted_13 = ["src"];
|
|
2254
|
+
const _hoisted_11 = { class: "fab-avatar-wrapper" };
|
|
2255
|
+
const _hoisted_12 = ["src"];
|
|
2197
2256
|
const currentTheme = "dark";
|
|
2198
2257
|
const _sfc_main = /* @__PURE__ */ vue.defineComponent({
|
|
2199
2258
|
__name: "voice-assistant",
|
|
@@ -2282,13 +2341,17 @@
|
|
|
2282
2341
|
tts.warmUpAudio();
|
|
2283
2342
|
await voice.toggleVoiceMode(targetState);
|
|
2284
2343
|
};
|
|
2285
|
-
const { voiceStatus,
|
|
2344
|
+
const { voiceStatus, wakeAnimating, isTranscribing } = voice;
|
|
2286
2345
|
const { isInvoking, currentTextContent, currentToolParts, executingTools, hasAnyContent, toolDisplayName } = agent;
|
|
2287
2346
|
aiChatbotX?.registerVoiceMethods({
|
|
2288
2347
|
stopBroadcast: async () => interruptCurrentResponse(),
|
|
2289
2348
|
start: () => toggleVoiceMode(true),
|
|
2290
2349
|
stop: () => toggleVoiceMode(false)
|
|
2291
2350
|
});
|
|
2351
|
+
aiChatbotX?.registerVoiceAssistant({
|
|
2352
|
+
agentInvoke: agent.invoke,
|
|
2353
|
+
agentAbort: agent.abort
|
|
2354
|
+
});
|
|
2292
2355
|
vue.onBeforeUnmount(async () => {
|
|
2293
2356
|
bubble.destroy();
|
|
2294
2357
|
agent.abort();
|
|
@@ -2376,15 +2439,14 @@
|
|
|
2376
2439
|
class: "assistant-fab",
|
|
2377
2440
|
onClick: _cache[0] || (_cache[0] = ($event) => toggleVoiceMode())
|
|
2378
2441
|
}, [
|
|
2379
|
-
vue.
|
|
2380
|
-
vue.createElementVNode("div", _hoisted_12, [
|
|
2442
|
+
vue.createElementVNode("div", _hoisted_11, [
|
|
2381
2443
|
vue.createElementVNode("img", {
|
|
2382
2444
|
src: __props.xLogo ? __props.xLogo : "/x.png",
|
|
2383
2445
|
alt: "voice assistant",
|
|
2384
2446
|
style: vue.normalizeStyle({
|
|
2385
2447
|
width: `${__props.xSize?.width || 88}px`
|
|
2386
2448
|
})
|
|
2387
|
-
}, null, 12,
|
|
2449
|
+
}, null, 12, _hoisted_12),
|
|
2388
2450
|
vue.createVNode(vue.Transition, { name: "indicator-fade" }, {
|
|
2389
2451
|
default: vue.withCtx(() => [
|
|
2390
2452
|
vue.unref(voiceStatus) === "listening" ? (vue.openBlock(), vue.createElementBlock("div", {
|
|
@@ -2426,7 +2488,7 @@
|
|
|
2426
2488
|
}
|
|
2427
2489
|
});
|
|
2428
2490
|
|
|
2429
|
-
const voiceAssistant = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
2491
|
+
const voiceAssistant = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-d1d9b351"]]);
|
|
2430
2492
|
|
|
2431
2493
|
var clientCommandKey = /* @__PURE__ */ ((clientCommandKey2) => {
|
|
2432
2494
|
clientCommandKey2["SET_THEME"] = "SiMeAgent_setTheme";
|