@xmanrui/dsh-im 3.0.2 → 3.0.4
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/lib/client.js +1 -7
- package/lib/index.js +196 -195
- package/package.json +1 -1
- package/plugin-src/client/styles.js +0 -6
- package/src/channels/wecom/wecom-bridge.mjs +48 -11
package/package.json
CHANGED
|
@@ -245,8 +245,6 @@ const CSS = String.raw`
|
|
|
245
245
|
.dim-panel .ddt-qrFrame, .dim-panel .ddt-countdown { width: min(270px, 100%); }
|
|
246
246
|
@container (max-width: 680px) {
|
|
247
247
|
.dim-panel .bxf-headingTools, .dim-panel .dxw-tools, .dim-panel .ddt-tools { gap: 6px; }
|
|
248
|
-
.dim-panel .dim-botCardTop { flex-direction: column; align-items: stretch; }
|
|
249
|
-
.dim-panel .dim-botHealthGroup { justify-items: start; }
|
|
250
248
|
.dim-panel .dim-bindActions { gap: 6px; }
|
|
251
249
|
.dim-panel .bxf-headingTools .dim-scanButton, .dim-panel .dxw-tools .dim-scanButton, .dim-panel .ddt-tools .dim-scanButton, .dim-panel .dim-credentialButton { gap: 5px; padding-inline: 8px; font-size: 12px; }
|
|
252
250
|
.dim-panel .dim-actionIcon { width: 13px; height: 13px; flex-basis: 13px; }
|
|
@@ -270,10 +268,6 @@ const CSS = String.raw`
|
|
|
270
268
|
.dim-rail { max-height: none; overflow: visible; padding-right: 1px; }
|
|
271
269
|
.dim-channel { min-height: 48px; }
|
|
272
270
|
}
|
|
273
|
-
@media (max-width: 720px) {
|
|
274
|
-
.dim-panel .dim-botCardTop { flex-direction: column; align-items: stretch; }
|
|
275
|
-
.dim-panel .dim-botHealthGroup { justify-items: start; }
|
|
276
|
-
}
|
|
277
271
|
@media (max-width: 560px) {
|
|
278
272
|
.dim-title { flex-direction: column; gap: 10px; }
|
|
279
273
|
.dim-title p { white-space: normal; }
|
|
@@ -296,12 +296,23 @@ function splitUtf8(text, maxBytes = MAX_REPLY_BYTES) {
|
|
|
296
296
|
return chunks;
|
|
297
297
|
}
|
|
298
298
|
|
|
299
|
-
function
|
|
300
|
-
if (update?.type === 'text') return update.text;
|
|
299
|
+
function thinkingProgressText(update) {
|
|
301
300
|
if (update?.type === 'tool') return t('正在使用{name}…', { name: update.name });
|
|
302
301
|
return update?.text;
|
|
303
302
|
}
|
|
304
303
|
|
|
304
|
+
function streamContent(thinkingText, answerText = '', { finish = false } = {}) {
|
|
305
|
+
const thinking = String(thinkingText ?? '')
|
|
306
|
+
.replace(/<\/?think>/gi, '')
|
|
307
|
+
.trim();
|
|
308
|
+
const answer = String(answerText ?? '').trim();
|
|
309
|
+
if (!thinking) return answer;
|
|
310
|
+
const thinkBlock = finish || answer
|
|
311
|
+
? `<think>${thinking}</think>`
|
|
312
|
+
: `<think>${thinking}`;
|
|
313
|
+
return answer ? `${thinkBlock}\n${answer}` : thinkBlock;
|
|
314
|
+
}
|
|
315
|
+
|
|
305
316
|
function artifactFailureText(fileName, error) {
|
|
306
317
|
const name = String(fileName ?? t('结果文件')).replace(/[\r\n]+/g, ' ').trim()
|
|
307
318
|
|| t('结果文件');
|
|
@@ -867,6 +878,8 @@ export class WecomHarnessBridge {
|
|
|
867
878
|
const key = conversationKey(frame);
|
|
868
879
|
let streamId = null;
|
|
869
880
|
let streamStarted = false;
|
|
881
|
+
let streamThinkingText = t('正在思考中…');
|
|
882
|
+
let streamAnswerText = '';
|
|
870
883
|
let batchSettled = batchSubmission === null;
|
|
871
884
|
let promptRecorded = false;
|
|
872
885
|
try {
|
|
@@ -920,7 +933,12 @@ export class WecomHarnessBridge {
|
|
|
920
933
|
|
|
921
934
|
streamId = this.#generateReqId('stream');
|
|
922
935
|
try {
|
|
923
|
-
await this.#client.replyStream(
|
|
936
|
+
await this.#client.replyStream(
|
|
937
|
+
frame,
|
|
938
|
+
streamId,
|
|
939
|
+
streamContent(streamThinkingText),
|
|
940
|
+
false,
|
|
941
|
+
);
|
|
924
942
|
streamStarted = true;
|
|
925
943
|
} catch (error) {
|
|
926
944
|
this.#logger.warn?.('[dsh-im:wecom] unable to start a stream; using an active reply:', error);
|
|
@@ -945,8 +963,15 @@ export class WecomHarnessBridge {
|
|
|
945
963
|
control: { owner: this, key },
|
|
946
964
|
onUpdate: streamStarted && typeof this.#client.replyStreamNonBlocking === 'function'
|
|
947
965
|
? async (update) => {
|
|
948
|
-
|
|
949
|
-
|
|
966
|
+
if (update?.type === 'text') {
|
|
967
|
+
streamAnswerText = update.text;
|
|
968
|
+
} else {
|
|
969
|
+
streamThinkingText = thinkingProgressText(update) || streamThinkingText;
|
|
970
|
+
}
|
|
971
|
+
const preview = splitUtf8(
|
|
972
|
+
streamContent(streamThinkingText, streamAnswerText),
|
|
973
|
+
)[0];
|
|
974
|
+
if (preview) await this.#client.replyStreamNonBlocking(frame, streamId, preview, false);
|
|
950
975
|
}
|
|
951
976
|
: undefined,
|
|
952
977
|
onInteraction: (interaction) => this.#handleInteraction(interaction, {
|
|
@@ -966,18 +991,20 @@ export class WecomHarnessBridge {
|
|
|
966
991
|
|
|
967
992
|
this.#signal?.throwIfAborted();
|
|
968
993
|
const displayAnswer = answerTextForDelivery(answer, artifacts);
|
|
969
|
-
const
|
|
994
|
+
const streamChunks = splitUtf8(
|
|
995
|
+
streamContent(streamThinkingText, displayAnswer, { finish: true }),
|
|
996
|
+
);
|
|
970
997
|
let finalSent = false;
|
|
971
998
|
let textReceipt = null;
|
|
972
999
|
let textSendError = null;
|
|
973
1000
|
try {
|
|
974
|
-
if (streamStarted &&
|
|
1001
|
+
if (streamStarted && streamChunks.length > 0) {
|
|
975
1002
|
try {
|
|
976
1003
|
const providerMessageIds = [];
|
|
977
|
-
const streamed = await this.#client.replyStream(frame, streamId,
|
|
1004
|
+
const streamed = await this.#client.replyStream(frame, streamId, streamChunks[0], true);
|
|
978
1005
|
const streamedMessageId = providerMessageId(streamed);
|
|
979
1006
|
if (streamedMessageId) providerMessageIds.push(streamedMessageId);
|
|
980
|
-
for (const chunk of
|
|
1007
|
+
for (const chunk of streamChunks.slice(1)) {
|
|
981
1008
|
const sent = await this.#client.sendMessage(
|
|
982
1009
|
chatId,
|
|
983
1010
|
{ msgtype: 'markdown', markdown: { content: chunk } },
|
|
@@ -1040,7 +1067,12 @@ export class WecomHarnessBridge {
|
|
|
1040
1067
|
}
|
|
1041
1068
|
if (error?.code === 'turn-stopped') {
|
|
1042
1069
|
if (streamStarted && streamId) {
|
|
1043
|
-
await this.#client.replyStream(
|
|
1070
|
+
await this.#client.replyStream(
|
|
1071
|
+
frame,
|
|
1072
|
+
streamId,
|
|
1073
|
+
streamContent(streamThinkingText, t('已停止。'), { finish: true }),
|
|
1074
|
+
true,
|
|
1075
|
+
)
|
|
1044
1076
|
.catch(() => undefined);
|
|
1045
1077
|
}
|
|
1046
1078
|
if (!promptRecorded) await this.#state.markSeen(messageId);
|
|
@@ -1063,7 +1095,12 @@ export class WecomHarnessBridge {
|
|
|
1063
1095
|
: errorText;
|
|
1064
1096
|
try {
|
|
1065
1097
|
if (streamStarted && streamId) {
|
|
1066
|
-
await this.#client.replyStream(
|
|
1098
|
+
await this.#client.replyStream(
|
|
1099
|
+
frame,
|
|
1100
|
+
streamId,
|
|
1101
|
+
streamContent(streamThinkingText, visibleError, { finish: true }),
|
|
1102
|
+
true,
|
|
1103
|
+
);
|
|
1067
1104
|
} else {
|
|
1068
1105
|
await this.#sendImmediate(frame, chatId, visibleError);
|
|
1069
1106
|
}
|