@huyooo/ai-chat-frontend-vue 0.1.2

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 (45) hide show
  1. package/dist/adapter.d.ts +87 -0
  2. package/dist/adapter.d.ts.map +1 -0
  3. package/dist/components/ChatInput.vue.d.ts +54 -0
  4. package/dist/components/ChatInput.vue.d.ts.map +1 -0
  5. package/dist/components/ChatPanel.vue.d.ts +38 -0
  6. package/dist/components/ChatPanel.vue.d.ts.map +1 -0
  7. package/dist/components/chat/SearchResultBlock.vue.d.ts +8 -0
  8. package/dist/components/chat/SearchResultBlock.vue.d.ts.map +1 -0
  9. package/dist/components/chat/ThinkingBlock.vue.d.ts +7 -0
  10. package/dist/components/chat/ThinkingBlock.vue.d.ts.map +1 -0
  11. package/dist/components/chat/ToolCallBlock.vue.d.ts +9 -0
  12. package/dist/components/chat/ToolCallBlock.vue.d.ts.map +1 -0
  13. package/dist/components/chat/messages/ExecutionSteps.vue.d.ts +13 -0
  14. package/dist/components/chat/messages/ExecutionSteps.vue.d.ts.map +1 -0
  15. package/dist/components/chat/messages/MessageBubble.vue.d.ts +28 -0
  16. package/dist/components/chat/messages/MessageBubble.vue.d.ts.map +1 -0
  17. package/dist/components/chat/ui/ChatHeader.vue.d.ts +34 -0
  18. package/dist/components/chat/ui/ChatHeader.vue.d.ts.map +1 -0
  19. package/dist/components/chat/ui/WelcomeMessage.vue.d.ts +7 -0
  20. package/dist/components/chat/ui/WelcomeMessage.vue.d.ts.map +1 -0
  21. package/dist/composables/useChat.d.ts +96 -0
  22. package/dist/composables/useChat.d.ts.map +1 -0
  23. package/dist/index.d.ts +37 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +1497 -0
  26. package/dist/preload/preload.d.ts +6 -0
  27. package/dist/preload/preload.d.ts.map +1 -0
  28. package/dist/style.css +1 -0
  29. package/dist/types/index.d.ts +107 -0
  30. package/dist/types/index.d.ts.map +1 -0
  31. package/package.json +59 -0
  32. package/src/adapter.ts +160 -0
  33. package/src/components/ChatInput.vue +649 -0
  34. package/src/components/ChatPanel.vue +309 -0
  35. package/src/components/chat/SearchResultBlock.vue +155 -0
  36. package/src/components/chat/ThinkingBlock.vue +109 -0
  37. package/src/components/chat/ToolCallBlock.vue +213 -0
  38. package/src/components/chat/messages/ExecutionSteps.vue +281 -0
  39. package/src/components/chat/messages/MessageBubble.vue +272 -0
  40. package/src/components/chat/ui/ChatHeader.vue +535 -0
  41. package/src/components/chat/ui/WelcomeMessage.vue +135 -0
  42. package/src/composables/useChat.ts +423 -0
  43. package/src/index.ts +82 -0
  44. package/src/preload/preload.ts +79 -0
  45. package/src/types/index.ts +164 -0
@@ -0,0 +1,6 @@
1
+ /**
2
+ * AI Chat 模块的 Preload 脚本(完全独立实现)
3
+ */
4
+ declare const _default: {};
5
+ export default _default;
6
+ //# sourceMappingURL=preload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preload.d.ts","sourceRoot":"","sources":["../../src/preload/preload.ts"],"names":[],"mappings":"AAAA;;GAEG;;AAyEH,wBAEE"}
package/dist/style.css ADDED
@@ -0,0 +1 @@
1
+ .chat-header[data-v-fd156e6a]{display:flex;align-items:center;height:40px;padding:0 12px;background:var(--chat-header-bg, #1e1e1e);border-bottom:1px solid var(--chat-border, #333);flex-shrink:0}.tabs-container[data-v-fd156e6a]{display:flex;align-items:center;gap:4px;flex:1;overflow-x:auto;padding-right:8px}.tabs-container[data-v-fd156e6a]::-webkit-scrollbar{display:none}.tab-item[data-v-fd156e6a]{position:relative;display:flex;align-items:center;gap:4px;padding:4px 8px;background:transparent;border:none;border-radius:4px;color:var(--chat-text-muted, #888);font-size:13px;font-weight:500;cursor:pointer;transition:all .15s;white-space:nowrap;max-width:120px;flex-shrink:0}.tab-item[data-v-fd156e6a]:hover{color:var(--chat-text, #ccc)}.tab-item.active[data-v-fd156e6a]{background:var(--chat-muted, #3c3c3c);color:var(--chat-text, #fff)}.tab-title[data-v-fd156e6a]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tab-close[data-v-fd156e6a]{display:none;width:16px;height:16px;padding:0;background:transparent;border:none;border-radius:2px;color:var(--chat-text-muted, #888);cursor:pointer;align-items:center;justify-content:center;flex-shrink:0}.tab-item:hover .tab-close[data-v-fd156e6a]{display:flex}.tab-close[data-v-fd156e6a]:hover{color:var(--chat-text, #fff);background:var(--chat-muted, #444)}.header-actions[data-v-fd156e6a]{display:flex;align-items:center;gap:2px;flex-shrink:0}.icon-btn[data-v-fd156e6a]{display:flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;background:transparent;border:none;border-radius:4px;color:var(--chat-text-muted, #888);cursor:pointer;transition:all .15s}.icon-btn[data-v-fd156e6a]:hover,.icon-btn.active[data-v-fd156e6a]{color:var(--chat-text, #fff)}.icon-btn.small[data-v-fd156e6a]{width:20px;height:20px}.dropdown-container[data-v-fd156e6a]{position:relative}.dropdown-panel[data-v-fd156e6a]{position:absolute;top:100%;right:0;margin-top:4px;background:var(--chat-dropdown-bg, #252526);border:1px solid rgba(255,255,255,.1);border-radius:8px;box-shadow:0 4px 16px #0006;z-index:100;overflow:hidden}.history-panel[data-v-fd156e6a]{width:280px}.more-panel[data-v-fd156e6a]{width:200px;padding:4px}.panel-header[data-v-fd156e6a]{display:flex;align-items:center;justify-content:space-between;padding:10px 12px;border-bottom:1px solid var(--chat-border, #333);font-size:12px;font-weight:500;color:var(--chat-text-muted, #888)}.panel-content[data-v-fd156e6a]{max-height:300px;overflow-y:auto}.history-item[data-v-fd156e6a]{display:flex;align-items:center;gap:8px;padding:10px 12px;cursor:pointer;transition:background .15s}.history-item[data-v-fd156e6a]:hover{background:#ffffff14}.history-item.active[data-v-fd156e6a]{background:#ffffff1a}.history-title[data-v-fd156e6a]{flex:1;font-size:13px;color:var(--chat-text, #ccc);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.history-date[data-v-fd156e6a]{font-size:11px;color:var(--chat-text-muted, #666);flex-shrink:0}.history-delete[data-v-fd156e6a]{display:none;width:20px;height:20px;padding:0;background:transparent;border:none;border-radius:4px;color:var(--chat-text-muted, #666);cursor:pointer;align-items:center;justify-content:center;flex-shrink:0}.history-item:hover .history-delete[data-v-fd156e6a]{display:flex}.history-delete[data-v-fd156e6a]:hover{color:var(--chat-destructive, #ef4444);background:var(--chat-destructive, #ef444420)}.empty-state[data-v-fd156e6a]{padding:20px;text-align:center;font-size:13px;color:var(--chat-text-muted, #666)}.menu-item[data-v-fd156e6a]{display:flex;align-items:center;gap:8px;width:100%;padding:8px 10px;background:transparent;border:none;border-radius:4px;font-size:13px;color:var(--chat-text-muted, #999);cursor:pointer;transition:all .15s;text-align:left}.menu-item[data-v-fd156e6a]:hover{background:#ffffff14;color:var(--chat-text, #ccc)}.menu-divider[data-v-fd156e6a]{height:1px;background:var(--chat-border, #333);margin:4px 0}.welcome-message[data-v-f478d3aa]{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;padding:32px 20px;text-align:center}.welcome-icon[data-v-f478d3aa]{display:flex;align-items:center;justify-content:center;width:80px;height:80px;background:#ffffff1a;border-radius:20px;color:var(--chat-text, #ccc);margin-bottom:20px}.welcome-title[data-v-f478d3aa]{font-size:20px;font-weight:600;color:var(--chat-text, #ccc);margin-bottom:8px}.welcome-desc[data-v-f478d3aa]{font-size:14px;color:var(--chat-text-muted, #888);margin-bottom:24px}.quick-actions[data-v-f478d3aa]{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;max-width:320px}.quick-btn[data-v-f478d3aa]{display:flex;align-items:center;gap:6px;padding:8px 14px;background:var(--chat-muted, #2d2d2d);border:1px solid var(--chat-border, #444);border-radius:8px;color:var(--chat-text, #ccc);font-size:13px;cursor:pointer;transition:all .15s}.quick-btn[data-v-f478d3aa]:hover{background:#ffffff1a;border-color:#fff3}.quick-icon[data-v-f478d3aa]{color:var(--chat-text-muted, #888)}.quick-btn:hover .quick-icon[data-v-f478d3aa]{color:var(--chat-text, #fff)}.chat-input[data-v-79ec50ab]{padding:12px}.chat-input.message-variant[data-v-79ec50ab]{padding:0;margin-bottom:16px}.input-container[data-v-79ec50ab]{display:flex;flex-direction:column;background:var(--chat-input-bg, #2d2d2d);border:1px solid var(--chat-border, #444);border-radius:12px;padding:12px;transition:border-color .15s}.input-container.focused[data-v-79ec50ab]{border-color:#fff3}.attachment-preview[data-v-79ec50ab]{margin-bottom:8px}.preview-images[data-v-79ec50ab]{display:flex;gap:6px;flex-wrap:wrap}.preview-item[data-v-79ec50ab]{position:relative}.preview-thumb[data-v-79ec50ab]{width:48px;height:48px;object-fit:cover;border-radius:8px;border:1px solid var(--chat-border, #444)}.preview-more[data-v-79ec50ab]{display:flex;align-items:center;justify-content:center;width:48px;height:48px;background:var(--chat-muted, #3c3c3c);border-radius:8px;color:var(--chat-text-muted, #888);font-size:12px}.remove-btn[data-v-79ec50ab]{position:absolute;top:-4px;right:-4px;width:16px;height:16px;display:flex;align-items:center;justify-content:center;background:var(--chat-bg, #1e1e1e);border:1px solid var(--chat-border, #444);border-radius:50%;color:var(--chat-text-muted, #888);cursor:pointer;padding:0}.remove-btn[data-v-79ec50ab]:hover{background:var(--chat-muted, #3c3c3c);color:var(--chat-text, #ccc)}.input-field-wrapper[data-v-79ec50ab]{margin-bottom:8px}.input-field[data-v-79ec50ab]{width:100%;background:transparent;border:none;padding:0;color:var(--chat-text, #ccc);font-size:14px;resize:none;min-height:24px;max-height:150px;line-height:1.5;font-family:inherit}.input-field[data-v-79ec50ab]:focus{outline:none}.input-field[data-v-79ec50ab]::placeholder{color:var(--chat-text-muted, #666)}.input-controls[data-v-79ec50ab]{display:flex;align-items:center;justify-content:space-between;gap:8px}.input-left[data-v-79ec50ab]{display:flex;align-items:center;gap:4px}.selector[data-v-79ec50ab]{position:relative;display:flex;align-items:center;gap:4px;padding:4px 8px;background:var(--chat-muted, #3c3c3c);border:none;border-radius:6px;font-size:12px;color:var(--chat-text-muted, #888);cursor:pointer;transition:all .15s}.selector[data-v-79ec50ab]:hover{background:var(--chat-muted-hover, #444);color:var(--chat-text, #ccc)}.chevron[data-v-79ec50ab]{color:var(--chat-text-muted, #666)}.dropdown-menu[data-v-79ec50ab]{position:absolute;bottom:100%;left:0;margin-bottom:4px;min-width:160px;background:var(--chat-dropdown-bg, #252526);border:1px solid rgba(255,255,255,.1);border-radius:8px;box-shadow:0 4px 16px #0006;z-index:100;padding:4px}.dropdown-item[data-v-79ec50ab]{display:flex;align-items:center;gap:8px;width:100%;padding:8px 10px;border:none;background:transparent;border-radius:4px;font-size:13px;color:var(--chat-text-muted, #999);cursor:pointer;transition:all .15s}.dropdown-item[data-v-79ec50ab]:hover{background:#ffffff14;color:var(--chat-text, #ccc)}.dropdown-item.active[data-v-79ec50ab]{background:#ffffff1a;color:var(--chat-text, #fff)}.check-icon[data-v-79ec50ab]{margin-left:auto;color:var(--chat-text, #ccc)}.input-right[data-v-79ec50ab]{display:flex;align-items:center;gap:2px}.icon-btn[data-v-79ec50ab]{display:flex;align-items:center;justify-content:center;width:28px;height:28px;background:transparent;border:none;border-radius:6px;color:var(--chat-text-muted, #666);cursor:pointer;transition:all .15s}.icon-btn[data-v-79ec50ab]:hover{color:var(--chat-text, #ccc)}.toggle-btn[data-v-79ec50ab]{display:flex;align-items:center;justify-content:center;width:28px;height:28px;background:transparent;border:none;border-radius:6px;color:var(--chat-text-muted, #666);cursor:pointer;transition:all .15s}.toggle-btn[data-v-79ec50ab]:hover{color:var(--chat-text, #ccc)}.toggle-btn.active[data-v-79ec50ab]{color:var(--chat-text, #fff);background:#ffffff1a}.send-btn[data-v-79ec50ab]{display:flex;align-items:center;justify-content:center;width:28px;height:28px;background:#ffffffe6;border:none;border-radius:6px;color:#1e1e1e;cursor:pointer;transition:all .15s}.send-btn[data-v-79ec50ab]:hover{background:#fff}.send-btn.loading[data-v-79ec50ab]{background:var(--chat-destructive, #ef4444)}.send-btn.loading[data-v-79ec50ab]:hover{background:var(--chat-destructive-hover, #dc2626)}.execution-steps[data-v-5ad7fab1]{display:flex;flex-direction:column;gap:4px;margin-bottom:8px}.step[data-v-5ad7fab1]{background:var(--chat-muted, #2d2d2d);border-radius:8px;overflow:hidden}.step-header[data-v-5ad7fab1]{display:flex;align-items:center;gap:8px;padding:8px 12px;cursor:pointer;transition:background .15s}.step-header[data-v-5ad7fab1]:hover{background:var(--chat-muted-hover, #3a3a3a)}.step-icon[data-v-5ad7fab1]{display:flex;align-items:center;justify-content:center;width:20px;height:20px;color:var(--chat-text-muted, #888)}.step-title[data-v-5ad7fab1]{flex:1;font-size:13px;color:var(--chat-text, #ccc)}.step-chevron[data-v-5ad7fab1]{color:var(--chat-text-muted, #666);transition:transform .2s}.step-chevron.expanded[data-v-5ad7fab1]{transform:rotate(180deg)}.step-content[data-v-5ad7fab1]{padding:8px 12px 12px;border-top:1px solid var(--chat-border, #333);margin-top:4px}.thinking-content[data-v-5ad7fab1]{font-size:13px;line-height:1.6;color:var(--chat-text-muted, #999);white-space:pre-wrap;word-break:break-word}.search-results[data-v-5ad7fab1]{display:flex;flex-direction:column;gap:8px}.search-result[data-v-5ad7fab1]{display:flex;flex-direction:column;gap:2px;padding:8px;background:var(--chat-bg, #1e1e1e);border-radius:6px;text-decoration:none;transition:background .15s}.search-result[data-v-5ad7fab1]:hover{background:var(--chat-muted-hover, #333)}.result-title[data-v-5ad7fab1]{font-size:13px;color:var(--chat-text, #ccc);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.search-result:hover .result-title[data-v-5ad7fab1]{color:var(--chat-text, #fff)}.result-url[data-v-5ad7fab1]{font-size:11px;color:var(--chat-text-muted, #666)}.tool-result[data-v-5ad7fab1]{font-size:12px;line-height:1.5;color:var(--chat-text-muted, #999);background:var(--chat-bg, #1e1e1e);padding:8px;border-radius:6px;overflow-x:auto;white-space:pre-wrap;word-break:break-word;font-family:SF Mono,Monaco,monospace;margin:0}.animate-spin[data-v-5ad7fab1]{animation:spin-5ad7fab1 1s linear infinite}@keyframes spin-5ad7fab1{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.text-green[data-v-5ad7fab1]{color:var(--chat-success, #22c55e)}.text-red[data-v-5ad7fab1]{color:var(--chat-destructive, #ef4444)}.message-bubble[data-v-bb746e4b]{padding:8px 0;animation:fadeIn-bb746e4b .2s ease}@keyframes fadeIn-bb746e4b{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.message-bubble.user[data-v-bb746e4b]{width:100%}.user-content[data-v-bb746e4b]{width:100%;background:var(--chat-muted, #2d2d2d);color:var(--chat-text, #ccc);padding:12px;border-radius:12px;border:1px solid var(--chat-border, #444)}.user-text[data-v-bb746e4b]{font-size:14px;line-height:1.5;white-space:pre-wrap;word-break:break-word}.user-images[data-v-bb746e4b]{display:flex;gap:8px;margin-top:8px;flex-wrap:wrap}.user-image[data-v-bb746e4b]{width:80px;height:80px;object-fit:cover;border-radius:8px;cursor:pointer;transition:transform .15s}.user-image[data-v-bb746e4b]:hover{transform:scale(1.05)}.message-bubble.assistant[data-v-bb746e4b]{position:relative}.assistant-content[data-v-bb746e4b]{max-width:100%}.assistant-text[data-v-bb746e4b]{font-size:14px;line-height:1.7;color:var(--chat-text, #ccc);font-weight:500;letter-spacing:.01em}.assistant-text[data-v-bb746e4b] .code-block{background:var(--chat-code-bg, #1f2937);color:var(--chat-code-text, #e5e7eb);padding:12px;border-radius:8px;margin:8px 0;overflow-x:auto;font-family:SF Mono,Monaco,monospace;font-size:13px}.assistant-text[data-v-bb746e4b] .inline-code{background:var(--chat-muted, #3c3c3c);color:var(--chat-text, #e5e7eb);padding:2px 6px;border-radius:4px;font-family:SF Mono,Monaco,monospace;font-size:13px}.loading-indicator[data-v-bb746e4b]{display:flex;gap:4px;padding:8px 0}.loading-dot[data-v-bb746e4b]{width:6px;height:6px;background:var(--chat-text-muted, #666);border-radius:50%;animation:pulse-bb746e4b 1.4s ease-in-out infinite}.loading-dot[data-v-bb746e4b]:nth-child(2){animation-delay:.2s}.loading-dot[data-v-bb746e4b]:nth-child(3){animation-delay:.4s}@keyframes pulse-bb746e4b{0%,to{opacity:.4;transform:scale(.8)}50%{opacity:1;transform:scale(1)}}.message-actions[data-v-bb746e4b]{display:flex;gap:4px;margin-top:8px;justify-content:flex-end}.action-btn[data-v-bb746e4b]{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;background:transparent;border-radius:4px;color:var(--chat-text-muted, #666);cursor:pointer;transition:all .15s}.action-btn[data-v-bb746e4b]:hover{background:var(--chat-muted, #3c3c3c);color:var(--chat-text, #ccc)}.chat-panel[data-v-2332ad8f]{display:flex;flex-direction:column;width:420px;height:100%;background:var(--chat-bg, #1e1e1e);border-left:1px solid var(--chat-border, #333);flex-shrink:0;overflow:hidden}.messages-container[data-v-2332ad8f]{flex:1;min-height:0;overflow-y:auto;padding:12px;scroll-behavior:smooth}.messages-container[data-v-2332ad8f]::-webkit-scrollbar{width:6px}.messages-container[data-v-2332ad8f]::-webkit-scrollbar-track{background:transparent}.messages-container[data-v-2332ad8f]::-webkit-scrollbar-thumb{background:var(--chat-scrollbar, rgba(255, 255, 255, .2));border-radius:3px}.messages-container[data-v-2332ad8f]::-webkit-scrollbar-thumb:hover{background:var(--chat-scrollbar-hover, rgba(255, 255, 255, .3))}.thinking-block[data-v-318aa171]{margin:8px 0;background:var(--chat-muted, #2d2d2d);border-radius:8px;overflow:hidden}.thinking-header[data-v-318aa171]{display:flex;align-items:center;gap:8px;width:100%;padding:10px 12px;border:none;background:transparent;cursor:pointer;transition:background .15s}.thinking-header[data-v-318aa171]:hover{background:var(--chat-muted-hover, #3a3a3a)}.thinking-icon[data-v-318aa171]{display:flex;align-items:center;justify-content:center;width:24px;height:24px;background:#ffffff1a;border-radius:50%;color:var(--chat-text, #ccc)}.spinning[data-v-318aa171]{animation:spin-318aa171 1s linear infinite}@keyframes spin-318aa171{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.thinking-title[data-v-318aa171]{flex:1;text-align:left;font-size:13px;color:var(--chat-text, #ccc);font-weight:500}.chevron[data-v-318aa171]{color:var(--chat-text-muted, #666);transition:transform .2s}.chevron.rotated[data-v-318aa171]{transform:rotate(180deg)}.thinking-content[data-v-318aa171]{padding:8px 12px 12px;border-top:1px solid var(--chat-border, #333);margin-top:4px}.thinking-text[data-v-318aa171]{font-size:13px;color:var(--chat-text-muted, #999);line-height:1.6;white-space:pre-wrap;word-break:break-word}.tool-call-block[data-v-7098f4a3]{margin:8px 0;background:var(--chat-muted, #2d2d2d);border-radius:8px;overflow:hidden}.tool-header[data-v-7098f4a3]{display:flex;align-items:center;gap:8px;padding:10px 12px;cursor:pointer;transition:background .15s}.tool-header[data-v-7098f4a3]:hover{background:var(--chat-muted-hover, #3a3a3a)}.tool-icon[data-v-7098f4a3]{display:flex;align-items:center;justify-content:center;width:24px;height:24px;background:var(--chat-muted, #3c3c3c);border-radius:4px;color:var(--chat-text-muted, #888)}.running .tool-icon[data-v-7098f4a3]{background:#ffffff1a;color:var(--chat-text, #ccc)}.success .tool-icon[data-v-7098f4a3]{background:var(--chat-success, #22c55e20);color:var(--chat-success, #22c55e)}.error .tool-icon[data-v-7098f4a3]{background:var(--chat-destructive, #ef444420);color:var(--chat-destructive, #ef4444)}.spinning[data-v-7098f4a3]{animation:spin-7098f4a3 1s linear infinite}@keyframes spin-7098f4a3{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.tool-name[data-v-7098f4a3]{flex:1;font-size:13px;font-weight:500;color:var(--chat-text, #ccc)}.chevron[data-v-7098f4a3]{color:var(--chat-text-muted, #666);transition:transform .2s}.chevron.rotated[data-v-7098f4a3]{transform:rotate(180deg)}.tool-args[data-v-7098f4a3]{padding:8px 12px;border-top:1px solid var(--chat-border, #333)}.arg-item[data-v-7098f4a3]{display:flex;gap:8px;font-size:12px;line-height:1.6}.arg-key[data-v-7098f4a3]{color:var(--chat-text-muted, #888);font-weight:500}.arg-value[data-v-7098f4a3]{color:var(--chat-text, #ccc);font-family:SF Mono,Monaco,monospace;word-break:break-all}.tool-result[data-v-7098f4a3]{border-top:1px solid var(--chat-border, #333);padding:8px 12px;background:var(--chat-bg, #1e1e1e)}.tool-result pre[data-v-7098f4a3]{margin:0;font-size:12px;color:var(--chat-text-muted, #999);white-space:pre-wrap;word-break:break-word;font-family:SF Mono,Monaco,monospace;max-height:200px;overflow-y:auto}.search-block[data-v-f1490d29]{margin:8px 0;background:var(--chat-muted, #2d2d2d);border-radius:8px;overflow:hidden}.search-header[data-v-f1490d29]{display:flex;align-items:center;gap:8px;padding:10px 12px;cursor:pointer;transition:background .15s}.search-header[data-v-f1490d29]:hover{background:var(--chat-muted-hover, #3a3a3a)}.search-icon[data-v-f1490d29]{display:flex;align-items:center;justify-content:center;width:24px;height:24px;background:#ffffff1a;border-radius:50%;color:var(--chat-text, #ccc)}.spinning[data-v-f1490d29]{animation:spin-f1490d29 1s linear infinite}@keyframes spin-f1490d29{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.search-title[data-v-f1490d29]{flex:1;font-size:13px;font-weight:500;color:var(--chat-text, #ccc)}.chevron[data-v-f1490d29]{color:var(--chat-text-muted, #666);transition:transform .2s}.chevron.rotated[data-v-f1490d29]{transform:rotate(180deg)}.search-results[data-v-f1490d29]{border-top:1px solid var(--chat-border, #333);padding:8px;display:flex;flex-direction:column;gap:6px}.result-item[data-v-f1490d29]{display:flex;flex-direction:column;gap:2px;padding:8px;background:var(--chat-bg, #1e1e1e);border-radius:6px;text-decoration:none;transition:background .15s}.result-item[data-v-f1490d29]:hover{background:var(--chat-muted-hover, #333)}.result-title[data-v-f1490d29]{font-size:13px;color:var(--chat-text, #ccc);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.result-item:hover .result-title[data-v-f1490d29]{color:var(--chat-text, #fff)}.result-url[data-v-f1490d29]{font-size:11px;color:var(--chat-text-muted, #666)}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * AI Chat 前端类型定义
3
+ */
4
+ /** 搜索结果 */
5
+ export interface SearchResult {
6
+ title: string;
7
+ url: string;
8
+ snippet: string;
9
+ }
10
+ /** 工具调用 */
11
+ export interface ToolCall {
12
+ name: string;
13
+ args?: Record<string, unknown>;
14
+ result?: string;
15
+ status: 'running' | 'success' | 'error';
16
+ }
17
+ /** 模型提供商 */
18
+ export type ModelProvider = 'openrouter' | 'doubao' | 'deepseek' | 'qwen' | 'gemini' | 'ark';
19
+ /** 模型配置 */
20
+ export interface ModelConfig {
21
+ provider: ModelProvider;
22
+ model: string;
23
+ displayName: string;
24
+ supportsTools: boolean;
25
+ supportsWebSearch: boolean;
26
+ supportedThinkingModes: ThinkingMode[];
27
+ }
28
+ /** 思考模式 */
29
+ export type ThinkingMode = 'enabled' | 'disabled';
30
+ /** 聊天模式 */
31
+ export type ChatMode = 'agent' | 'ask';
32
+ /** 聊天消息 */
33
+ export interface ChatMessage {
34
+ id: string;
35
+ role: 'user' | 'assistant';
36
+ content: string;
37
+ images?: string[];
38
+ thinking?: string;
39
+ thinkingComplete?: boolean;
40
+ searchResults?: SearchResult[];
41
+ searching?: boolean;
42
+ toolCalls?: ToolCall[];
43
+ copied?: boolean;
44
+ loading?: boolean;
45
+ timestamp?: Date;
46
+ }
47
+ /** 会话记录 */
48
+ export interface SessionRecord {
49
+ id: string;
50
+ title: string;
51
+ model: string;
52
+ mode: ChatMode;
53
+ createdAt: Date;
54
+ updatedAt: Date;
55
+ }
56
+ /** 消息记录 */
57
+ export interface MessageRecord {
58
+ id: string;
59
+ sessionId: string;
60
+ role: 'user' | 'assistant';
61
+ content: string;
62
+ thinking?: string;
63
+ toolCalls?: string;
64
+ searchResults?: string;
65
+ timestamp: Date;
66
+ }
67
+ /** 默认模型列表 */
68
+ export declare const DEFAULT_MODELS: ModelConfig[];
69
+ /** @deprecated 使用 SessionRecord */
70
+ export interface ChatSession {
71
+ id: string;
72
+ title: string;
73
+ messages: ChatMessage[];
74
+ createdAt: Date;
75
+ updatedAt: Date;
76
+ }
77
+ /** 音视频操作类型 */
78
+ export interface MediaOperation {
79
+ id: string;
80
+ type: 'clip' | 'transcode' | 'merge' | 'extract_audio' | 'add_subtitle' | 'analyze';
81
+ description: string;
82
+ sourceFiles: string[];
83
+ targetFile?: string;
84
+ parameters?: Record<string, unknown>;
85
+ status?: 'pending' | 'applied' | 'rejected';
86
+ preview?: string;
87
+ }
88
+ /** @deprecated 使用字符串枚举 */
89
+ export type AiModel = 'gemini-3-pro-preview' | 'gemini-3-pro-image-preview';
90
+ export declare enum FileType {
91
+ FOLDER = "folder",
92
+ IMAGE = "image",
93
+ VIDEO = "video",
94
+ AUDIO = "audio",
95
+ TEXT = "text",
96
+ PDF = "pdf",
97
+ CODE = "code",
98
+ ARCHIVE = "archive",
99
+ OTHER = "other"
100
+ }
101
+ export interface DiffStat {
102
+ file: string;
103
+ additions: number;
104
+ deletions: number;
105
+ type: 'modified' | 'added' | 'deleted';
106
+ }
107
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,WAAW;AACX,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,WAAW;AACX,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,CAAA;CACxC;AAED,YAAY;AACZ,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAA;AAE5F,WAAW;AACX,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,aAAa,CAAA;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,OAAO,CAAA;IACtB,iBAAiB,EAAE,OAAO,CAAA;IAC1B,sBAAsB,EAAE,YAAY,EAAE,CAAA;CACvC;AAED,WAAW;AACX,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,UAAU,CAAA;AAEjD,WAAW;AACX,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,KAAK,CAAA;AAEtC,WAAW;AACX,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,GAAG,WAAW,CAAA;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,aAAa,CAAC,EAAE,YAAY,EAAE,CAAA;IAC9B,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAA;IACtB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,SAAS,CAAC,EAAE,IAAI,CAAA;CACjB;AAED,WAAW;AACX,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,QAAQ,CAAA;IACd,SAAS,EAAE,IAAI,CAAA;IACf,SAAS,EAAE,IAAI,CAAA;CAChB;AAED,WAAW;AACX,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,GAAG,WAAW,CAAA;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,IAAI,CAAA;CAChB;AAED,aAAa;AACb,eAAO,MAAM,cAAc,EAAE,WAAW,EAyCvC,CAAA;AAID,mCAAmC;AACnC,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,WAAW,EAAE,CAAA;IACvB,SAAS,EAAE,IAAI,CAAA;IACf,SAAS,EAAE,IAAI,CAAA;CAChB;AAED,cAAc;AACd,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,OAAO,GAAG,eAAe,GAAG,cAAc,GAAG,SAAS,CAAA;IACnF,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,MAAM,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,UAAU,CAAA;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,0BAA0B;AAC1B,MAAM,MAAM,OAAO,GAAG,sBAAsB,GAAG,4BAA4B,CAAA;AAE3E,oBAAY,QAAQ;IAClB,MAAM,WAAW;IACjB,KAAK,UAAU;IACf,KAAK,UAAU;IACf,KAAK,UAAU;IACf,IAAI,SAAS;IACb,GAAG,QAAQ;IACX,IAAI,SAAS;IACb,OAAO,YAAY;IACnB,KAAK,UAAU;CAChB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,SAAS,CAAA;CACvC"}
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@huyooo/ai-chat-frontend-vue",
3
+ "version": "0.1.2",
4
+ "description": "AI Chat Frontend - Vue components with adapter pattern",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "development": "./src/index.ts",
13
+ "import": "./dist/index.js",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "./style.css": "./dist/style.css"
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "src"
21
+ ],
22
+ "scripts": {
23
+ "build": "vite build",
24
+ "dev": "vite build --watch",
25
+ "typecheck": "vue-tsc --noEmit",
26
+ "clean": "rm -rf dist"
27
+ },
28
+ "peerDependencies": {
29
+ "vue": "^3.4.0"
30
+ },
31
+ "dependencies": {
32
+ "lucide-vue-next": "^0.460.0",
33
+ "vscode-uri": "^3.1.0"
34
+ },
35
+ "devDependencies": {
36
+ "@rollup/pluginutils": "^5.3.0",
37
+ "@types/node": "^22.0.0",
38
+ "@vitejs/plugin-vue": "^5.0.0",
39
+ "local-pkg": "^1.1.2",
40
+ "lucide-vue-next": "^0.460.0",
41
+ "magic-string": "^0.30.21",
42
+ "typescript": "^5.0.0",
43
+ "vite": "^6.0.0",
44
+ "vite-plugin-dts": "^4.0.0",
45
+ "vue": "^3.4.0",
46
+ "vue-tsc": "^2.0.0"
47
+ },
48
+ "keywords": [
49
+ "ai",
50
+ "chat",
51
+ "vue",
52
+ "frontend"
53
+ ],
54
+ "author": "huyooo",
55
+ "license": "MIT",
56
+ "publishConfig": {
57
+ "access": "public"
58
+ }
59
+ }
package/src/adapter.ts ADDED
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Chat Adapter 接口定义
3
+ * 解耦前端组件与后端通信方式
4
+ */
5
+
6
+ import type { SessionRecord, MessageRecord, ChatMode, ThinkingMode, SearchResult, ToolCall } from './types'
7
+
8
+ /** 聊天进度类型 */
9
+ export type ChatProgressType =
10
+ | 'thinking'
11
+ | 'search_start'
12
+ | 'search_result'
13
+ | 'tool_call'
14
+ | 'tool_result'
15
+ | 'text_delta'
16
+ | 'text'
17
+ | 'done'
18
+ | 'error'
19
+
20
+ /** 思考数据 */
21
+ export interface ThinkingData {
22
+ content: string
23
+ isComplete: boolean
24
+ }
25
+
26
+ /** 工具调用数据 */
27
+ export interface ToolCallData {
28
+ name: string
29
+ args: Record<string, unknown>
30
+ }
31
+
32
+ /** 工具结果数据 */
33
+ export interface ToolResultData {
34
+ name: string
35
+ result: string
36
+ }
37
+
38
+ /** 图片数据 */
39
+ export interface ImageData {
40
+ base64: string
41
+ mimeType: string
42
+ }
43
+
44
+ /** 聊天进度事件 */
45
+ export interface ChatProgress {
46
+ type: ChatProgressType
47
+ data: string | ThinkingData | ToolCallData | ToolResultData | { results: SearchResult[] }
48
+ }
49
+
50
+ /** 发送消息选项 */
51
+ export interface SendMessageOptions {
52
+ mode: ChatMode
53
+ model: string
54
+ enableWebSearch: boolean
55
+ thinkingMode: ThinkingMode
56
+ }
57
+
58
+ /** 创建会话选项 */
59
+ export interface CreateSessionOptions {
60
+ title: string
61
+ model: string
62
+ mode: ChatMode
63
+ }
64
+
65
+ /** 更新会话选项 */
66
+ export interface UpdateSessionOptions {
67
+ title?: string
68
+ model?: string
69
+ mode?: ChatMode
70
+ }
71
+
72
+ /** 保存消息选项 */
73
+ export interface SaveMessageOptions {
74
+ sessionId: string
75
+ role: 'user' | 'assistant'
76
+ content: string
77
+ thinking?: string
78
+ toolCalls?: string
79
+ searchResults?: string
80
+ }
81
+
82
+ /**
83
+ * Chat Adapter 接口
84
+ * 所有后端通信实现都需要实现此接口
85
+ */
86
+ export interface ChatAdapter {
87
+ /** 获取所有会话 */
88
+ getSessions(): Promise<SessionRecord[]>
89
+
90
+ /** 创建新会话 */
91
+ createSession(options: CreateSessionOptions): Promise<SessionRecord>
92
+
93
+ /** 更新会话 */
94
+ updateSession(sessionId: string, options: UpdateSessionOptions): Promise<void>
95
+
96
+ /** 删除会话 */
97
+ deleteSession(sessionId: string): Promise<void>
98
+
99
+ /** 获取会话消息 */
100
+ getMessages(sessionId: string): Promise<MessageRecord[]>
101
+
102
+ /** 保存消息 */
103
+ saveMessage(options: SaveMessageOptions): Promise<MessageRecord>
104
+
105
+ /** 发送消息并获取流式响应 */
106
+ sendMessage(
107
+ content: string,
108
+ options: SendMessageOptions,
109
+ images?: string[]
110
+ ): AsyncGenerator<ChatProgress, void, unknown>
111
+
112
+ /** 取消当前请求 */
113
+ cancel(): void
114
+
115
+ /** 设置工作目录 */
116
+ setWorkingDir?(dir: string): void
117
+ }
118
+
119
+ /**
120
+ * 创建空 Adapter(用于测试或无后端场景)
121
+ */
122
+ export function createNullAdapter(): ChatAdapter {
123
+ return {
124
+ async getSessions() {
125
+ return []
126
+ },
127
+ async createSession(options) {
128
+ return {
129
+ id: Date.now().toString(),
130
+ title: options.title,
131
+ model: options.model,
132
+ mode: options.mode,
133
+ createdAt: new Date(),
134
+ updatedAt: new Date(),
135
+ }
136
+ },
137
+ async updateSession() {},
138
+ async deleteSession() {},
139
+ async getMessages() {
140
+ return []
141
+ },
142
+ async saveMessage(options) {
143
+ return {
144
+ id: Date.now().toString(),
145
+ sessionId: options.sessionId,
146
+ role: options.role,
147
+ content: options.content,
148
+ thinking: options.thinking,
149
+ toolCalls: options.toolCalls,
150
+ searchResults: options.searchResults,
151
+ timestamp: new Date(),
152
+ }
153
+ },
154
+ async *sendMessage() {
155
+ yield { type: 'text', data: '无可用的 Adapter' }
156
+ yield { type: 'done', data: '' }
157
+ },
158
+ cancel() {},
159
+ }
160
+ }