Skip to content

Commit d181de4

Browse files
author
linyuan.yang
committed
explorer
1 parent feb0d79 commit d181de4

9 files changed

Lines changed: 150 additions & 85 deletions

File tree

packages/admin/src/components/modals/SkillViewerModal.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ defineExpose({ open })
6262
<style scoped>
6363
.skill-viewer-body {
6464
height: 70vh;
65+
display: flex;
66+
min-height: 0;
6567
overflow: hidden;
6668
margin: calc(-1 * var(--sui-sp-7)) calc(-1 * var(--sui-sp-8));
6769
}

packages/chat-ui/src/components/Explorer.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,15 @@ function refresh() {
136136
display: flex;
137137
flex-direction: column;
138138
height: 100%;
139+
min-height: 0;
139140
overflow: hidden;
140141
background: var(--chatui-bg);
141142
}
143+
.chatui-explorer > :deep(.chatui-file-explorer),
144+
.chatui-explorer > :deep(.chatui-git-explorer) {
145+
flex: 1 1 0;
146+
min-height: 0;
147+
}
142148
.chatui-explorer-header {
143149
display: flex;
144150
align-items: center;

packages/chat-ui/src/components/FileExplorer.vue

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ function clampTreeSize(size: number, mode = resizeMode.value): number {
317317
}
318318
319319
function syncResizeMode() {
320-
const width = explorerEl.value?.clientWidth ?? window.innerWidth
320+
const width = window.innerWidth
321321
const nextMode = width <= 768 ? 'vertical' : 'horizontal'
322322
resizeMode.value = nextMode
323323
if (nextMode === 'vertical') {
@@ -365,7 +365,14 @@ onMounted(() => {
365365
</script>
366366

367367
<template>
368-
<div ref="explorerEl" class="chatui-file-explorer" :class="{ 'chatui-file-explorer--resizing': resizing }">
368+
<div
369+
ref="explorerEl"
370+
class="chatui-file-explorer"
371+
:class="{
372+
'chatui-file-explorer--resizing': resizing,
373+
'chatui-file-explorer--vertical': resizeMode === 'vertical',
374+
}"
375+
>
369376
<STree class="chatui-explorer-tree" :style="treeStyle">
370377
<div v-if="!hasRoot" class="chatui-explorer-empty-tip">{{ L.explorerPickRootHint }}</div>
371378
<div v-else-if="rootLoading && rootRows.length === 0" class="chatui-explorer-empty-tip">{{ L.loading }}</div>
@@ -602,34 +609,33 @@ onMounted(() => {
602609
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.12);
603610
}
604611
605-
@media (max-width: 768px) {
606-
.chatui-file-explorer { flex-direction: column; }
607-
.chatui-explorer-tree {
608-
width: 100% !important;
609-
min-width: 0;
610-
max-width: none;
611-
min-height: 140px;
612-
max-height: calc(100% - 180px);
613-
}
614-
.chatui-explorer-splitter {
615-
width: 100%;
616-
height: 8px;
617-
margin: -4px 0;
618-
cursor: row-resize;
619-
}
620-
.chatui-explorer-splitter::after {
621-
top: 3px;
622-
bottom: auto;
623-
left: 0;
624-
right: 0;
625-
width: auto;
626-
height: 1px;
627-
}
628-
.chatui-file-explorer--resizing .chatui-explorer-splitter {
629-
cursor: row-resize;
630-
}
631-
.chatui-explorer-image {
632-
max-height: calc(100vh - 320px);
633-
}
612+
.chatui-file-explorer--vertical { flex-direction: column; }
613+
.chatui-file-explorer--vertical .chatui-explorer-tree {
614+
width: 100% !important;
615+
min-width: 0;
616+
max-width: none;
617+
min-height: 140px;
618+
max-height: calc(100% - 180px);
619+
align-self: auto;
620+
}
621+
.chatui-file-explorer--vertical .chatui-explorer-splitter {
622+
width: 100%;
623+
height: 8px;
624+
margin: -4px 0;
625+
cursor: row-resize;
626+
}
627+
.chatui-file-explorer--vertical .chatui-explorer-splitter::after {
628+
top: 3px;
629+
bottom: auto;
630+
left: 0;
631+
right: 0;
632+
width: auto;
633+
height: 1px;
634+
}
635+
.chatui-file-explorer--vertical.chatui-file-explorer--resizing .chatui-explorer-splitter {
636+
cursor: row-resize;
637+
}
638+
.chatui-file-explorer--vertical .chatui-explorer-image {
639+
max-height: calc(100vh - 320px);
634640
}
635641
</style>

packages/chat-ui/src/components/GitExplorer.vue

Lines changed: 44 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ function clampTreeSize(size: number, mode = resizeMode.value): number {
348348
}
349349
350350
function syncResizeMode() {
351-
const width = explorerEl.value?.clientWidth ?? window.innerWidth
351+
const width = window.innerWidth
352352
const nextMode = width <= 768 ? 'vertical' : 'horizontal'
353353
resizeMode.value = nextMode
354354
if (nextMode === 'vertical') {
@@ -396,7 +396,14 @@ onMounted(() => {
396396
</script>
397397

398398
<template>
399-
<div ref="explorerEl" class="chatui-git-explorer" :class="{ 'chatui-git-explorer--resizing': resizing }">
399+
<div
400+
ref="explorerEl"
401+
class="chatui-git-explorer"
402+
:class="{
403+
'chatui-git-explorer--resizing': resizing,
404+
'chatui-git-explorer--vertical': resizeMode === 'vertical',
405+
}"
406+
>
400407
<STree class="chatui-explorer-tree" :style="treeStyle">
401408
<div v-if="!props.root" class="chatui-explorer-empty-tip">{{ L.explorerPickRootHint }}</div>
402409
<div v-else-if="gitLoading && gitItems.length === 0" class="chatui-explorer-empty-tip">{{ L.loading }}</div>
@@ -797,41 +804,40 @@ onMounted(() => {
797804
color: var(--chatui-diff-add-fg, #116329);
798805
}
799806
800-
@media (max-width: 768px) {
801-
.chatui-git-explorer { flex-direction: column; }
802-
.chatui-explorer-tree {
803-
width: 100% !important;
804-
min-width: 0;
805-
max-width: none;
806-
min-height: 140px;
807-
max-height: calc(100% - 180px);
808-
}
809-
.chatui-explorer-splitter {
810-
width: 100%;
811-
height: 8px;
812-
margin: -4px 0;
813-
cursor: row-resize;
814-
}
815-
.chatui-explorer-splitter::after {
816-
top: 3px;
817-
bottom: auto;
818-
left: 0;
819-
right: 0;
820-
width: auto;
821-
height: 1px;
822-
}
823-
.chatui-git-explorer--resizing .chatui-explorer-splitter {
824-
cursor: row-resize;
825-
}
826-
.chatui-explorer-toolbar {
827-
grid-template-columns: 1fr;
828-
align-items: stretch;
829-
}
830-
.chatui-explorer-diff-tabs {
831-
justify-self: start;
832-
}
833-
.chatui-explorer-git-toolbar-right {
834-
justify-content: flex-start;
835-
}
807+
.chatui-git-explorer--vertical { flex-direction: column; }
808+
.chatui-git-explorer--vertical .chatui-explorer-tree {
809+
width: 100% !important;
810+
min-width: 0;
811+
max-width: none;
812+
min-height: 140px;
813+
max-height: calc(100% - 180px);
814+
align-self: auto;
815+
}
816+
.chatui-git-explorer--vertical .chatui-explorer-splitter {
817+
width: 100%;
818+
height: 8px;
819+
margin: -4px 0;
820+
cursor: row-resize;
821+
}
822+
.chatui-git-explorer--vertical .chatui-explorer-splitter::after {
823+
top: 3px;
824+
bottom: auto;
825+
left: 0;
826+
right: 0;
827+
width: auto;
828+
height: 1px;
829+
}
830+
.chatui-git-explorer--vertical.chatui-git-explorer--resizing .chatui-explorer-splitter {
831+
cursor: row-resize;
832+
}
833+
.chatui-git-explorer--vertical .chatui-explorer-toolbar {
834+
grid-template-columns: 1fr;
835+
align-items: stretch;
836+
}
837+
.chatui-git-explorer--vertical .chatui-explorer-diff-tabs {
838+
justify-self: start;
839+
}
840+
.chatui-git-explorer--vertical .chatui-explorer-git-toolbar-right {
841+
justify-content: flex-start;
836842
}
837843
</style>

packages/chat-ui/src/components/MessageList.vue

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ function isEmbeddedTool(msg: StoredMessage): boolean {
146146
<span>▸</span><span>{{ L.think }}</span>
147147
</div>
148148
</div>
149-
<ContentParts :content="msg.message.content" @open-image="openLightbox" />
149+
<ContentParts :content="msg.message.content" plain @open-image="openLightbox" />
150150
</div>
151151
</div>
152152

@@ -186,8 +186,10 @@ function isEmbeddedTool(msg: StoredMessage): boolean {
186186
@click="toggleToolCall(tc.id)"
187187
>
188188
<span class="tool-call-name">{{ tc.name }}</span>
189-
<span v-if="inlineArgs(tc)" class="tool-call-inline-args">{{ inlineArgs(tc) }}</span>
190-
<span v-if="toolResultPreviewMap.get(tc.id)" class="tool-call-result-preview">↳ {{ toolResultPreviewMap.get(tc.id) }}</span>
189+
<span class="tool-call-summary">
190+
<span v-if="inlineArgs(tc)" class="tool-call-inline-args" :title="inlineArgs(tc)">{{ inlineArgs(tc) }}</span>
191+
<span v-if="toolResultPreviewMap.get(tc.id)" class="tool-call-result-preview" :title="toolResultPreviewMap.get(tc.id)">↳ {{ toolResultPreviewMap.get(tc.id) }}</span>
192+
</span>
191193
</button>
192194
<div class="tool-call-detail" :class="{ show: isToolCallExpanded(tc.id) }">
193195
<div class="tool-call-args">{{ JSON.stringify(tc.args, null, 2) }}</div>
@@ -427,33 +429,58 @@ function isEmbeddedTool(msg: StoredMessage): boolean {
427429
color: inherit;
428430
padding: 6px 10px;
429431
cursor: pointer;
430-
display: flex;
431-
align-items: center;
432+
display: grid;
433+
grid-template-columns: auto 1fr auto;
434+
align-items: start;
432435
gap: 8px;
433436
font-weight: 500;
434437
font: inherit;
435438
text-align: left;
436439
user-select: none;
440+
min-width: 0;
437441
}
438442
.tool-call-header::after {
439443
content: '';
440444
font-size: 10px;
441445
color: var(--chatui-fg-secondary);
442-
margin-left: auto;
446+
align-self: center;
443447
}
444448
.tool-call-header.expanded::after { content: ''; }
445449
.tool-call-name {
446450
font-family: monospace;
447451
font-size: 12px;
452+
padding: 1px 6px;
453+
border-radius: 4px;
454+
background: var(--chatui-bg-code, var(--chatui-bg-soft));
455+
color: var(--chatui-fg);
456+
white-space: nowrap;
457+
align-self: center;
458+
}
459+
.tool-call-summary {
460+
display: flex;
461+
flex-direction: column;
462+
gap: 2px;
463+
min-width: 0;
464+
overflow: hidden;
465+
padding-top: 2px;
448466
}
449467
.tool-call-inline-args {
450468
font-family: monospace;
451469
font-size: 11px;
452470
color: var(--chatui-fg-secondary);
471+
white-space: nowrap;
472+
overflow: hidden;
473+
text-overflow: ellipsis;
474+
min-width: 0;
453475
}
454476
.tool-call-result-preview {
455477
font-size: 11px;
456478
color: var(--chatui-fg-secondary);
479+
white-space: nowrap;
480+
overflow: hidden;
481+
text-overflow: ellipsis;
482+
min-width: 0;
483+
opacity: 0.85;
457484
}
458485
.tool-call-header.expanded .tool-call-result-preview { display: none; }
459486
.tool-call-detail { display: none; }

packages/chat-ui/src/components/_ContentParts.vue

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,35 @@ import { ContentPartType } from '../types'
44
import type { DisplayContent, DisplayPart } from '../types'
55
import { getContentParts, renderMd } from '../messageRender'
66
7-
type RenderedDisplayPart = DisplayPart & { html?: string }
7+
type RenderedDisplayPart = DisplayPart & { html?: string; text?: string }
88
99
const props = withDefaults(defineProps<{
1010
content: DisplayContent | null | undefined
1111
textClass?: string
1212
showAudio?: boolean
13+
/** 关闭 markdown 渲染,按纯文本显示(保留换行) */
14+
plain?: boolean
1315
}>(), {
1416
textClass: 'md-content',
1517
showAudio: true,
18+
plain: false,
1619
})
1720
1821
const emit = defineEmits<{ openImage: [url: string] }>()
1922
2023
const renderedParts = computed<RenderedDisplayPart[]>(() =>
21-
getContentParts(props.content).map((part) => (
22-
part.type === ContentPartType.Text
23-
? { ...part, html: renderMd(part.text ?? '') }
24-
: part
25-
)),
24+
getContentParts(props.content).map((part) => {
25+
if (part.type !== ContentPartType.Text) return part
26+
if (props.plain) return { ...part, text: part.text ?? '' }
27+
return { ...part, html: renderMd(part.text ?? '') }
28+
}),
2629
)
2730
</script>
2831

2932
<template>
3033
<template v-for="(part, idx) in renderedParts" :key="idx">
31-
<div v-if="part.type === ContentPartType.Text" :class="textClass" v-html="part.html" />
34+
<div v-if="part.type === ContentPartType.Text && plain" :class="['plain-content', textClass]">{{ part.text }}</div>
35+
<div v-else-if="part.type === ContentPartType.Text" :class="textClass" v-html="part.html" />
3236
<div v-else-if="part.type === ContentPartType.Image" class="inline-image">
3337
<img :src="part.url" class="inline-image-thumb" @click="emit('openImage', part.url!)" />
3438
</div>
@@ -37,3 +41,10 @@ const renderedParts = computed<RenderedDisplayPart[]>(() =>
3741
</div>
3842
</template>
3943
</template>
44+
45+
<style scoped>
46+
.plain-content {
47+
white-space: pre-wrap;
48+
word-break: break-word;
49+
}
50+
</style>

packages/scorpio.ai/src/Agents/Single/SingleAgentService.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { ILoggerService } from "../../Logger";
1515
import { normalizeToMCPResult, MCPContentType, type MCPToolResult } from '../../Tools';
1616
import { AgentServiceBase, GraphNodeType, ToolApproval, IAgentCallback, AgentCancelledError, DEFAULT_MAX_HISTORY_TOKENS, ChatMessage, MessageRole, type TokenUsage } from "../AgentServiceBase";
1717
import type { MessageContent } from "../../Saver/IAgentSaverService";
18-
import { contentToString } from "../../Utils/contentUtils";
18+
import { contentToString, truncateForLog } from "../../Utils/contentUtils";
1919

2020
export {
2121
GraphNodeType,
@@ -293,7 +293,7 @@ export class SingleAgentService extends AgentServiceBase {
293293
additional_kwargs: thinkId ? { thinkId } : undefined,
294294
});
295295
} catch (error: any) {
296-
toolMessages.push({ role: MessageRole.Tool, tool_call_id: toolCall.id || "", content: `Execute Tool ${toolCall.name} Error: ${error.message}`, status: "error" });
296+
toolMessages.push({ role: MessageRole.Tool, tool_call_id: toolCall.id || "", content: `Execute Tool ${toolCall.name} Error: ${truncateForLog(error.message)}`, status: "error" });
297297
}
298298
}
299299

packages/scorpio.ai/src/User/MessageDispatcher.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { CommandContext, CommandRegistry, ICommand } from "../Command";
33
import { AgentCancelledError } from "../Agents/AgentServiceBase";
44
import { GlobalLoggerService, ILogger } from "../Logger";
55
import type { MessageContent } from "../Saver/IAgentSaverService";
6+
import { truncateForLog } from "../Utils/contentUtils";
67

78
export enum MessageType { Command = 'command', AI = 'ai' }
89

@@ -62,7 +63,7 @@ export abstract class MessageDispatcher {
6263
if (e instanceof AgentCancelledError) {
6364
this.logger?.info(`处理已取消[${logSuffix}]: ${queryText}`);
6465
} else {
65-
this.logger?.error(`处理出错[${logSuffix}]: ${queryText} : ${e.message}\n${e.stack}`);
66+
this.logger?.error(`处理出错[${logSuffix}]: ${queryText} : ${truncateForLog(e.message)}\n${truncateForLog(e.stack)}`);
6667
}
6768
error = e;
6869
} finally {

0 commit comments

Comments
 (0)