@huyooo/ai-chat-frontend-vue 0.1.6 → 0.1.7

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.
Files changed (159) hide show
  1. package/README.md +367 -0
  2. package/dist/adapter.d.ts +7 -7
  3. package/dist/adapter.d.ts.map +1 -1
  4. package/dist/components/ChatPanel.vue.d.ts +120 -9
  5. package/dist/components/ChatPanel.vue.d.ts.map +1 -1
  6. package/dist/components/common/ConfirmDialog.vue.d.ts +30 -0
  7. package/dist/components/common/ConfirmDialog.vue.d.ts.map +1 -0
  8. package/dist/components/common/CopyButton.vue.d.ts +18 -0
  9. package/dist/components/common/CopyButton.vue.d.ts.map +1 -0
  10. package/dist/components/common/IndexingSettings.vue.d.ts +3 -0
  11. package/dist/components/common/IndexingSettings.vue.d.ts.map +1 -0
  12. package/dist/components/common/SettingsPanel.vue.d.ts +16 -0
  13. package/dist/components/common/SettingsPanel.vue.d.ts.map +1 -0
  14. package/dist/components/common/Toast.vue.d.ts +18 -0
  15. package/dist/components/common/Toast.vue.d.ts.map +1 -0
  16. package/dist/components/common/ToggleSwitch.vue.d.ts +10 -0
  17. package/dist/components/common/ToggleSwitch.vue.d.ts.map +1 -0
  18. package/dist/components/{chat/ui → header}/ChatHeader.vue.d.ts +5 -3
  19. package/dist/components/header/ChatHeader.vue.d.ts.map +1 -0
  20. package/dist/components/input/AtFilePicker.vue.d.ts +21 -0
  21. package/dist/components/input/AtFilePicker.vue.d.ts.map +1 -0
  22. package/dist/components/{ChatInput.vue.d.ts → input/ChatInput.vue.d.ts} +16 -14
  23. package/dist/components/input/ChatInput.vue.d.ts.map +1 -0
  24. package/dist/components/input/DropdownSelector.vue.d.ts +42 -0
  25. package/dist/components/input/DropdownSelector.vue.d.ts.map +1 -0
  26. package/dist/components/input/ImagePreviewModal.vue.d.ts +17 -0
  27. package/dist/components/input/ImagePreviewModal.vue.d.ts.map +1 -0
  28. package/dist/components/input/at-views/AtBranchView.vue.d.ts +18 -0
  29. package/dist/components/input/at-views/AtBranchView.vue.d.ts.map +1 -0
  30. package/dist/components/input/at-views/AtBrowserView.vue.d.ts +18 -0
  31. package/dist/components/input/at-views/AtBrowserView.vue.d.ts.map +1 -0
  32. package/dist/components/input/at-views/AtChatsView.vue.d.ts +18 -0
  33. package/dist/components/input/at-views/AtChatsView.vue.d.ts.map +1 -0
  34. package/dist/components/input/at-views/AtDocsView.vue.d.ts +18 -0
  35. package/dist/components/input/at-views/AtDocsView.vue.d.ts.map +1 -0
  36. package/dist/components/input/at-views/AtFilesView.vue.d.ts +23 -0
  37. package/dist/components/input/at-views/AtFilesView.vue.d.ts.map +1 -0
  38. package/dist/components/input/at-views/AtTerminalsView.vue.d.ts +18 -0
  39. package/dist/components/input/at-views/AtTerminalsView.vue.d.ts.map +1 -0
  40. package/dist/components/message/MessageBubble.vue.d.ts +45 -0
  41. package/dist/components/message/MessageBubble.vue.d.ts.map +1 -0
  42. package/dist/components/message/PartsRenderer.vue.d.ts +15 -0
  43. package/dist/components/message/PartsRenderer.vue.d.ts.map +1 -0
  44. package/dist/components/message/WelcomeMessage.vue.d.ts +14 -0
  45. package/dist/components/message/WelcomeMessage.vue.d.ts.map +1 -0
  46. package/dist/components/message/blocks/CodeBlock.vue.d.ts +11 -0
  47. package/dist/components/message/blocks/CodeBlock.vue.d.ts.map +1 -0
  48. package/dist/components/{chat/SearchResultBlock.vue.d.ts → message/blocks/TextBlock.vue.d.ts} +3 -4
  49. package/dist/components/message/blocks/TextBlock.vue.d.ts.map +1 -0
  50. package/dist/components/message/blocks/index.d.ts +6 -0
  51. package/dist/components/message/blocks/index.d.ts.map +1 -0
  52. package/dist/components/message/parts/CollapsibleCard.vue.d.ts +45 -0
  53. package/dist/components/message/parts/CollapsibleCard.vue.d.ts.map +1 -0
  54. package/dist/components/{chat/ToolCallBlock.vue.d.ts → message/parts/ErrorPart.vue.d.ts} +4 -5
  55. package/dist/components/message/parts/ErrorPart.vue.d.ts.map +1 -0
  56. package/dist/components/{chat/ThinkingBlock.vue.d.ts → message/parts/ImagePart.vue.d.ts} +3 -3
  57. package/dist/components/message/parts/ImagePart.vue.d.ts.map +1 -0
  58. package/dist/components/message/parts/SearchPart.vue.d.ts +12 -0
  59. package/dist/components/message/parts/SearchPart.vue.d.ts.map +1 -0
  60. package/dist/components/{chat/messages/ExecutionSteps.vue.d.ts → message/parts/TextPart.vue.d.ts} +2 -9
  61. package/dist/components/message/parts/TextPart.vue.d.ts.map +1 -0
  62. package/dist/components/message/parts/ThinkingPart.vue.d.ts +12 -0
  63. package/dist/components/message/parts/ThinkingPart.vue.d.ts.map +1 -0
  64. package/dist/components/message/parts/ToolCallPart.vue.d.ts +19 -0
  65. package/dist/components/message/parts/ToolCallPart.vue.d.ts.map +1 -0
  66. package/dist/components/message/parts/ToolResultPart.vue.d.ts +14 -0
  67. package/dist/components/message/parts/ToolResultPart.vue.d.ts.map +1 -0
  68. package/dist/components/message/parts/index.d.ts +12 -0
  69. package/dist/components/message/parts/index.d.ts.map +1 -0
  70. package/dist/components/message/tool-results/DefaultToolResult.vue.d.ts +4 -0
  71. package/dist/components/message/tool-results/DefaultToolResult.vue.d.ts.map +1 -0
  72. package/dist/components/message/tool-results/SearchResults.vue.d.ts +4 -0
  73. package/dist/components/message/tool-results/SearchResults.vue.d.ts.map +1 -0
  74. package/dist/components/message/tool-results/WeatherCard.vue.d.ts +4 -0
  75. package/dist/components/message/tool-results/WeatherCard.vue.d.ts.map +1 -0
  76. package/dist/components/message/tool-results/index.d.ts +7 -0
  77. package/dist/components/message/tool-results/index.d.ts.map +1 -0
  78. package/dist/components/message/welcome-types.d.ts +28 -0
  79. package/dist/components/message/welcome-types.d.ts.map +1 -0
  80. package/dist/composables/useChat.d.ts +99 -44
  81. package/dist/composables/useChat.d.ts.map +1 -1
  82. package/dist/composables/useImageUpload.d.ts +55 -0
  83. package/dist/composables/useImageUpload.d.ts.map +1 -0
  84. package/dist/index.d.ts +25 -26
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.js +55871 -1252
  87. package/dist/style.css +1 -1
  88. package/dist/types/index.d.ts +113 -53
  89. package/dist/types/index.d.ts.map +1 -1
  90. package/dist/utils/fileIcon.d.ts +13 -0
  91. package/dist/utils/fileIcon.d.ts.map +1 -0
  92. package/package.json +12 -6
  93. package/src/adapter.ts +12 -70
  94. package/src/components/ChatPanel.vue +329 -110
  95. package/src/components/common/ConfirmDialog.vue +208 -0
  96. package/src/components/common/CopyButton.vue +71 -0
  97. package/src/components/common/IndexingSettings.vue +580 -0
  98. package/src/components/common/SettingsPanel.vue +293 -0
  99. package/src/components/common/Toast.vue +90 -0
  100. package/src/components/common/ToggleSwitch.vue +75 -0
  101. package/src/components/{chat/ui → header}/ChatHeader.vue +170 -93
  102. package/src/components/input/AtFilePicker.vue +657 -0
  103. package/src/components/input/ChatInput.vue +653 -0
  104. package/src/components/input/DropdownSelector.vue +322 -0
  105. package/src/components/input/ImagePreviewModal.vue +238 -0
  106. package/src/components/input/at-views/AtBranchView.vue +63 -0
  107. package/src/components/input/at-views/AtBrowserView.vue +63 -0
  108. package/src/components/input/at-views/AtChatsView.vue +63 -0
  109. package/src/components/input/at-views/AtDocsView.vue +63 -0
  110. package/src/components/input/at-views/AtFilesView.vue +255 -0
  111. package/src/components/input/at-views/AtTerminalsView.vue +63 -0
  112. package/src/components/message/ContentRenderer.vue +61 -0
  113. package/src/components/message/MessageBubble.vue +411 -0
  114. package/src/components/message/PartsRenderer.vue +101 -0
  115. package/src/components/message/ToolResultRenderer.vue +27 -0
  116. package/src/components/message/WelcomeMessage.vue +308 -0
  117. package/src/components/message/blocks/CodeBlock.vue +113 -0
  118. package/src/components/message/blocks/TextBlock.vue +21 -0
  119. package/src/components/message/blocks/index.ts +6 -0
  120. package/src/components/message/parts/CollapsibleCard.vue +135 -0
  121. package/src/components/message/parts/ErrorPart.vue +51 -0
  122. package/src/components/message/parts/ImagePart.vue +98 -0
  123. package/src/components/message/parts/SearchPart.vue +101 -0
  124. package/src/components/message/parts/TextPart.vue +28 -0
  125. package/src/components/message/parts/ThinkingPart.vue +54 -0
  126. package/src/components/message/parts/ToolCallPart.vue +460 -0
  127. package/src/components/message/parts/ToolResultPart.vue +78 -0
  128. package/src/components/message/parts/index.ts +13 -0
  129. package/src/components/message/tool-results/DefaultToolResult.vue +43 -0
  130. package/src/components/message/tool-results/SearchResults.vue +133 -0
  131. package/src/components/message/tool-results/WeatherCard.vue +139 -0
  132. package/src/components/message/tool-results/index.ts +7 -0
  133. package/src/components/message/welcome-types.ts +47 -0
  134. package/src/composables/useChat.ts +807 -155
  135. package/src/composables/useImageUpload.ts +228 -0
  136. package/src/index.ts +93 -46
  137. package/src/styles.css +47 -0
  138. package/src/types/index.ts +146 -98
  139. package/src/utils/fileIcon.ts +49 -0
  140. package/dist/components/ChatInput.vue.d.ts.map +0 -1
  141. package/dist/components/chat/SearchResultBlock.vue.d.ts.map +0 -1
  142. package/dist/components/chat/ThinkingBlock.vue.d.ts.map +0 -1
  143. package/dist/components/chat/ToolCallBlock.vue.d.ts.map +0 -1
  144. package/dist/components/chat/messages/ExecutionSteps.vue.d.ts.map +0 -1
  145. package/dist/components/chat/messages/MessageBubble.vue.d.ts +0 -28
  146. package/dist/components/chat/messages/MessageBubble.vue.d.ts.map +0 -1
  147. package/dist/components/chat/ui/ChatHeader.vue.d.ts.map +0 -1
  148. package/dist/components/chat/ui/WelcomeMessage.vue.d.ts +0 -7
  149. package/dist/components/chat/ui/WelcomeMessage.vue.d.ts.map +0 -1
  150. package/dist/preload/preload.d.ts +0 -6
  151. package/dist/preload/preload.d.ts.map +0 -1
  152. package/src/components/ChatInput.vue +0 -649
  153. package/src/components/chat/SearchResultBlock.vue +0 -155
  154. package/src/components/chat/ThinkingBlock.vue +0 -109
  155. package/src/components/chat/ToolCallBlock.vue +0 -213
  156. package/src/components/chat/messages/ExecutionSteps.vue +0 -281
  157. package/src/components/chat/messages/MessageBubble.vue +0 -272
  158. package/src/components/chat/ui/WelcomeMessage.vue +0 -135
  159. package/src/preload/preload.ts +0 -79
@@ -1,155 +0,0 @@
1
- <template>
2
- <div class="search-block">
3
- <div class="search-header" @click="expanded = !expanded">
4
- <div class="search-icon">
5
- <Loader2 v-if="searching" :size="14" class="spinning" />
6
- <Globe v-else :size="14" />
7
- </div>
8
- <span class="search-title">
9
- {{ searching ? '正在搜索...' : `找到 ${results.length} 条结果` }}
10
- </span>
11
- <ChevronDown
12
- v-if="!searching && results.length > 0"
13
- :size="14"
14
- :class="['chevron', { rotated: expanded }]"
15
- />
16
- </div>
17
-
18
- <!-- 搜索结果列表 -->
19
- <div v-if="!searching && expanded && results.length > 0" class="search-results">
20
- <a
21
- v-for="(item, index) in results.slice(0, 5)"
22
- :key="index"
23
- :href="item.url"
24
- target="_blank"
25
- class="result-item"
26
- >
27
- <span class="result-title">{{ item.title }}</span>
28
- <span class="result-url">{{ formatUrl(item.url) }}</span>
29
- </a>
30
- </div>
31
- </div>
32
- </template>
33
-
34
- <script setup lang="ts">
35
- import { ref } from 'vue';
36
- import { Globe, Loader2, ChevronDown } from 'lucide-vue-next';
37
- import type { SearchResult } from '../../types';
38
-
39
- defineProps<{
40
- results: SearchResult[];
41
- searching: boolean;
42
- }>();
43
-
44
- const expanded = ref(true);
45
-
46
- function formatUrl(url: string): string {
47
- try {
48
- return new URL(url).hostname;
49
- } catch {
50
- return url;
51
- }
52
- }
53
- </script>
54
-
55
- <style scoped>
56
- .search-block {
57
- margin: 8px 0;
58
- background: var(--chat-muted, #2d2d2d);
59
- border-radius: 8px;
60
- overflow: hidden;
61
- }
62
-
63
- .search-header {
64
- display: flex;
65
- align-items: center;
66
- gap: 8px;
67
- padding: 10px 12px;
68
- cursor: pointer;
69
- transition: background 0.15s;
70
- }
71
-
72
- .search-header:hover {
73
- background: var(--chat-muted-hover, #3a3a3a);
74
- }
75
-
76
- .search-icon {
77
- display: flex;
78
- align-items: center;
79
- justify-content: center;
80
- width: 24px;
81
- height: 24px;
82
- background: rgba(255, 255, 255, 0.1);
83
- border-radius: 50%;
84
- color: var(--chat-text, #ccc);
85
- }
86
-
87
- .spinning {
88
- animation: spin 1s linear infinite;
89
- }
90
-
91
- @keyframes spin {
92
- from {
93
- transform: rotate(0deg);
94
- }
95
- to {
96
- transform: rotate(360deg);
97
- }
98
- }
99
-
100
- .search-title {
101
- flex: 1;
102
- font-size: 13px;
103
- font-weight: 500;
104
- color: var(--chat-text, #ccc);
105
- }
106
-
107
- .chevron {
108
- color: var(--chat-text-muted, #666);
109
- transition: transform 0.2s;
110
- }
111
-
112
- .chevron.rotated {
113
- transform: rotate(180deg);
114
- }
115
-
116
- .search-results {
117
- border-top: 1px solid var(--chat-border, #333);
118
- padding: 8px;
119
- display: flex;
120
- flex-direction: column;
121
- gap: 6px;
122
- }
123
-
124
- .result-item {
125
- display: flex;
126
- flex-direction: column;
127
- gap: 2px;
128
- padding: 8px;
129
- background: var(--chat-bg, #1e1e1e);
130
- border-radius: 6px;
131
- text-decoration: none;
132
- transition: background 0.15s;
133
- }
134
-
135
- .result-item:hover {
136
- background: var(--chat-muted-hover, #333);
137
- }
138
-
139
- .result-title {
140
- font-size: 13px;
141
- color: var(--chat-text, #ccc);
142
- overflow: hidden;
143
- text-overflow: ellipsis;
144
- white-space: nowrap;
145
- }
146
-
147
- .result-item:hover .result-title {
148
- color: var(--chat-text, #fff);
149
- }
150
-
151
- .result-url {
152
- font-size: 11px;
153
- color: var(--chat-text-muted, #666);
154
- }
155
- </style>
@@ -1,109 +0,0 @@
1
- <template>
2
- <div :class="['thinking-block', { expanded }]">
3
- <button class="thinking-header" @click="expanded = !expanded">
4
- <div class="thinking-icon">
5
- <Loader2 v-if="!isComplete" :size="14" class="spinning" />
6
- <Lightbulb v-else :size="14" />
7
- </div>
8
- <span class="thinking-title">{{ isComplete ? '思考完成' : '正在思考...' }}</span>
9
- <ChevronDown :size="14" :class="['chevron', { rotated: expanded }]" />
10
- </button>
11
-
12
- <div v-if="expanded && content" class="thinking-content">
13
- <div class="thinking-text">{{ content }}</div>
14
- </div>
15
- </div>
16
- </template>
17
-
18
- <script setup lang="ts">
19
- import { ref } from 'vue';
20
- import { Loader2, Lightbulb, ChevronDown } from 'lucide-vue-next';
21
-
22
- defineProps<{
23
- content: string;
24
- isComplete: boolean;
25
- }>();
26
-
27
- const expanded = ref(false);
28
- </script>
29
-
30
- <style scoped>
31
- .thinking-block {
32
- margin: 8px 0;
33
- background: var(--chat-muted, #2d2d2d);
34
- border-radius: 8px;
35
- overflow: hidden;
36
- }
37
-
38
- .thinking-header {
39
- display: flex;
40
- align-items: center;
41
- gap: 8px;
42
- width: 100%;
43
- padding: 10px 12px;
44
- border: none;
45
- background: transparent;
46
- cursor: pointer;
47
- transition: background 0.15s;
48
- }
49
-
50
- .thinking-header:hover {
51
- background: var(--chat-muted-hover, #3a3a3a);
52
- }
53
-
54
- .thinking-icon {
55
- display: flex;
56
- align-items: center;
57
- justify-content: center;
58
- width: 24px;
59
- height: 24px;
60
- background: rgba(255, 255, 255, 0.1);
61
- border-radius: 50%;
62
- color: var(--chat-text, #ccc);
63
- }
64
-
65
- .spinning {
66
- animation: spin 1s linear infinite;
67
- }
68
-
69
- @keyframes spin {
70
- from {
71
- transform: rotate(0deg);
72
- }
73
- to {
74
- transform: rotate(360deg);
75
- }
76
- }
77
-
78
- .thinking-title {
79
- flex: 1;
80
- text-align: left;
81
- font-size: 13px;
82
- color: var(--chat-text, #ccc);
83
- font-weight: 500;
84
- }
85
-
86
- .chevron {
87
- color: var(--chat-text-muted, #666);
88
- transition: transform 0.2s;
89
- }
90
-
91
- .chevron.rotated {
92
- transform: rotate(180deg);
93
- }
94
-
95
- .thinking-content {
96
- padding: 0 12px 12px;
97
- border-top: 1px solid var(--chat-border, #333);
98
- margin-top: 4px;
99
- padding-top: 8px;
100
- }
101
-
102
- .thinking-text {
103
- font-size: 13px;
104
- color: var(--chat-text-muted, #999);
105
- line-height: 1.6;
106
- white-space: pre-wrap;
107
- word-break: break-word;
108
- }
109
- </style>
@@ -1,213 +0,0 @@
1
- <template>
2
- <div :class="['tool-call-block', status]">
3
- <div class="tool-header" @click="expanded = !expanded">
4
- <div class="tool-icon">
5
- <Loader2 v-if="status === 'running'" :size="14" class="spinning" />
6
- <Check v-else-if="status === 'success'" :size="14" />
7
- <X v-else-if="status === 'error'" :size="14" />
8
- <component v-else :is="toolIcon" :size="14" />
9
- </div>
10
- <span class="tool-name">{{ displayName }}</span>
11
- <ChevronDown
12
- v-if="result"
13
- :size="14"
14
- :class="['chevron', { rotated: expanded }]"
15
- />
16
- </div>
17
-
18
- <!-- 参数展示 -->
19
- <div v-if="args && Object.keys(args).length > 0 && expanded" class="tool-args">
20
- <div v-for="(value, key) in args" :key="key" class="arg-item">
21
- <span class="arg-key">{{ key }}:</span>
22
- <span class="arg-value">{{ formatValue(value) }}</span>
23
- </div>
24
- </div>
25
-
26
- <!-- 结果展示 -->
27
- <div v-if="result && expanded" class="tool-result">
28
- <pre>{{ result }}</pre>
29
- </div>
30
- </div>
31
- </template>
32
-
33
- <script setup lang="ts">
34
- import { ref, computed, markRaw } from 'vue';
35
- import {
36
- Terminal,
37
- Image,
38
- Video,
39
- Search,
40
- FileText,
41
- Loader2,
42
- Check,
43
- X,
44
- ChevronDown,
45
- } from 'lucide-vue-next';
46
-
47
- const props = defineProps<{
48
- name: string;
49
- args?: Record<string, unknown>;
50
- result?: string;
51
- status: 'running' | 'success' | 'error';
52
- }>();
53
-
54
- const expanded = ref(false);
55
-
56
- // 工具显示名称
57
- const displayName = computed(() => {
58
- const names: Record<string, string> = {
59
- execute_command: '执行命令',
60
- analyze_image: '分析图片',
61
- generate_image: '生成图片',
62
- analyze_video: '分析视频',
63
- web_search: '网络搜索',
64
- read_file: '读取文件',
65
- write_file: '写入文件',
66
- list_directory: '列出目录',
67
- create_directory: '创建目录',
68
- delete_file: '删除文件',
69
- move_file: '移动文件',
70
- search_files: '搜索文件',
71
- };
72
- return names[props.name] || props.name;
73
- });
74
-
75
- // 工具图标
76
- const toolIcon = computed(() => {
77
- const icons: Record<string, unknown> = {
78
- execute_command: markRaw(Terminal),
79
- analyze_image: markRaw(Image),
80
- generate_image: markRaw(Image),
81
- analyze_video: markRaw(Video),
82
- web_search: markRaw(Search),
83
- };
84
- return icons[props.name] || markRaw(FileText);
85
- });
86
-
87
- // 格式化参数值
88
- function formatValue(value: unknown): string {
89
- if (typeof value === 'string') {
90
- return value.length > 50 ? value.substring(0, 50) + '...' : value;
91
- }
92
- return JSON.stringify(value);
93
- }
94
- </script>
95
-
96
- <style scoped>
97
- .tool-call-block {
98
- margin: 8px 0;
99
- background: var(--chat-muted, #2d2d2d);
100
- border-radius: 8px;
101
- overflow: hidden;
102
- }
103
-
104
- .tool-header {
105
- display: flex;
106
- align-items: center;
107
- gap: 8px;
108
- padding: 10px 12px;
109
- cursor: pointer;
110
- transition: background 0.15s;
111
- }
112
-
113
- .tool-header:hover {
114
- background: var(--chat-muted-hover, #3a3a3a);
115
- }
116
-
117
- .tool-icon {
118
- display: flex;
119
- align-items: center;
120
- justify-content: center;
121
- width: 24px;
122
- height: 24px;
123
- background: var(--chat-muted, #3c3c3c);
124
- border-radius: 4px;
125
- color: var(--chat-text-muted, #888);
126
- }
127
-
128
- .running .tool-icon {
129
- background: rgba(255, 255, 255, 0.1);
130
- color: var(--chat-text, #ccc);
131
- }
132
-
133
- .success .tool-icon {
134
- background: var(--chat-success, #22c55e20);
135
- color: var(--chat-success, #22c55e);
136
- }
137
-
138
- .error .tool-icon {
139
- background: var(--chat-destructive, #ef444420);
140
- color: var(--chat-destructive, #ef4444);
141
- }
142
-
143
- .spinning {
144
- animation: spin 1s linear infinite;
145
- }
146
-
147
- @keyframes spin {
148
- from {
149
- transform: rotate(0deg);
150
- }
151
- to {
152
- transform: rotate(360deg);
153
- }
154
- }
155
-
156
- .tool-name {
157
- flex: 1;
158
- font-size: 13px;
159
- font-weight: 500;
160
- color: var(--chat-text, #ccc);
161
- }
162
-
163
- .chevron {
164
- color: var(--chat-text-muted, #666);
165
- transition: transform 0.2s;
166
- }
167
-
168
- .chevron.rotated {
169
- transform: rotate(180deg);
170
- }
171
-
172
- /* 参数展示 */
173
- .tool-args {
174
- padding: 8px 12px;
175
- border-top: 1px solid var(--chat-border, #333);
176
- }
177
-
178
- .arg-item {
179
- display: flex;
180
- gap: 8px;
181
- font-size: 12px;
182
- line-height: 1.6;
183
- }
184
-
185
- .arg-key {
186
- color: var(--chat-text-muted, #888);
187
- font-weight: 500;
188
- }
189
-
190
- .arg-value {
191
- color: var(--chat-text, #ccc);
192
- font-family: 'SF Mono', Monaco, monospace;
193
- word-break: break-all;
194
- }
195
-
196
- /* 结果展示 */
197
- .tool-result {
198
- border-top: 1px solid var(--chat-border, #333);
199
- padding: 8px 12px;
200
- background: var(--chat-bg, #1e1e1e);
201
- }
202
-
203
- .tool-result pre {
204
- margin: 0;
205
- font-size: 12px;
206
- color: var(--chat-text-muted, #999);
207
- white-space: pre-wrap;
208
- word-break: break-word;
209
- font-family: 'SF Mono', Monaco, monospace;
210
- max-height: 200px;
211
- overflow-y: auto;
212
- }
213
- </style>