Spaces:
Runtime error
Runtime error
Merge xsai integration with MCP features
Browse files- Combined xsai SDK integration with existing MCP functionality
- Resolved merge conflicts in server/index.js and package.json
- Both xsai AI model connections and MCP server management now work together
- Updated dependencies to include both xsai packages and MCP SDK
- Regenerated package-lock.json to reflect all dependencies
This merge brings together:
- xsai-powered AI streaming and summarization
- MCP server discovery and tool execution
- Enhanced reasoning extraction capabilities
- Unified server architecture supporting both features
- CHANGELOG.md +24 -0
- README.md +38 -0
- XSAI_INTEGRATION_SUMMARY.md +120 -0
- package-lock.json +153 -113
- package.json +4 -2
- server/index.js +96 -68
- src/App.jsx +74 -21
- src/components/ChatList.jsx +138 -30
- src/components/ChatWindow.jsx +1 -19
- src/index.css +68 -18
- tailwind.config.js +99 -6
- test-xsai.js +94 -0
CHANGELOG.md
CHANGED
|
@@ -4,6 +4,30 @@ All notable changes to this project will be documented in this file.
|
|
| 4 |
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
| 5 |
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
| 6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
## [0.1.1] - 2025-03-23
|
| 8 |
|
| 9 |
### Added
|
|
|
|
| 4 |
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
| 5 |
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
| 6 |
|
| 7 |
+
## [0.2.0] - 2025-07-24
|
| 8 |
+
|
| 9 |
+
### Added
|
| 10 |
+
- xsai integration for LLM provider connections
|
| 11 |
+
- Automatic reasoning extraction using `@xsai/utils-reasoning`
|
| 12 |
+
- Test script for xsai integration (`test-xsai.js`)
|
| 13 |
+
- Enhanced documentation for xsai usage
|
| 14 |
+
|
| 15 |
+
### Changed
|
| 16 |
+
- **BREAKING**: Migrated from `node-fetch` to xsai SDK for all AI model connections
|
| 17 |
+
- Chat endpoint now uses `@xsai/stream-text` for streaming responses
|
| 18 |
+
- Summarization endpoint now uses `@xsai/generate-text` for text generation
|
| 19 |
+
- Improved error handling and streaming reliability
|
| 20 |
+
- Enhanced reasoning process extraction and display
|
| 21 |
+
|
| 22 |
+
### Removed
|
| 23 |
+
- `node-fetch` dependency (replaced by xsai packages)
|
| 24 |
+
|
| 25 |
+
### Technical Details
|
| 26 |
+
- Server now uses xsai's `streamText` and `generateText` functions
|
| 27 |
+
- Automatic extraction of thinking processes from model responses
|
| 28 |
+
- Better streaming performance and error handling
|
| 29 |
+
- Runtime-agnostic AI SDK support
|
| 30 |
+
|
| 31 |
## [0.1.1] - 2025-03-23
|
| 32 |
|
| 33 |
### Added
|
README.md
CHANGED
|
@@ -37,6 +37,8 @@ A modern React-based chat application that provides a unique interface for inter
|
|
| 37 |
- π οΈ **Modern Stack**: Built with React and Vite for optimal performance and development experience
|
| 38 |
- π§ͺ **Quality Assured**: Comprehensive unit tests ensure reliable functionality
|
| 39 |
- π **Local Data Storage**: All data is stored locally for enhanced privacy and security
|
|
|
|
|
|
|
| 40 |
|
| 41 |
## Getting Started
|
| 42 |
|
|
@@ -93,3 +95,39 @@ A separate profile for conversation summarization:
|
|
| 93 |
- **Model Name**: The model to use for summarization
|
| 94 |
|
| 95 |
All settings are stored locally for privacy and security. You can manage multiple chat profiles and switch between them as needed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
- π οΈ **Modern Stack**: Built with React and Vite for optimal performance and development experience
|
| 38 |
- π§ͺ **Quality Assured**: Comprehensive unit tests ensure reliable functionality
|
| 39 |
- π **Local Data Storage**: All data is stored locally for enhanced privacy and security
|
| 40 |
+
- β‘ **xsai Integration**: Powered by xsai (extra-small AI SDK) for efficient and lightweight AI model connections
|
| 41 |
+
- π§© **Reasoning Extraction**: Automatic extraction and visualization of AI reasoning processes using xsai utilities
|
| 42 |
|
| 43 |
## Getting Started
|
| 44 |
|
|
|
|
| 95 |
- **Model Name**: The model to use for summarization
|
| 96 |
|
| 97 |
All settings are stored locally for privacy and security. You can manage multiple chat profiles and switch between them as needed.
|
| 98 |
+
|
| 99 |
+
## xsai Integration π€
|
| 100 |
+
|
| 101 |
+
This application now uses [xsai](https://github.com/moeru-ai/xsai) - an extra-small AI SDK for efficient LLM connections. The integration provides:
|
| 102 |
+
|
| 103 |
+
### Key Benefits
|
| 104 |
+
- **Lightweight**: Minimal dependencies and small bundle size
|
| 105 |
+
- **Runtime Agnostic**: Works in Node.js, Deno, Bun, and browsers
|
| 106 |
+
- **Streaming Support**: Built-in streaming capabilities for real-time responses
|
| 107 |
+
- **Reasoning Extraction**: Automatic extraction of thinking processes from model responses
|
| 108 |
+
|
| 109 |
+
### Technical Implementation
|
| 110 |
+
- **Chat Streaming**: Uses `@xsai/stream-text` for real-time message streaming
|
| 111 |
+
- **Summarization**: Uses `@xsai/generate-text` for conversation title generation
|
| 112 |
+
- **Reasoning Processing**: Uses `@xsai/utils-reasoning` to extract and display thinking processes
|
| 113 |
+
|
| 114 |
+
### Testing xsai Integration
|
| 115 |
+
|
| 116 |
+
To test the xsai integration independently:
|
| 117 |
+
|
| 118 |
+
1. Edit the `test-xsai.js` file with your API credentials
|
| 119 |
+
2. Run the test script:
|
| 120 |
+
|
| 121 |
+
```bash
|
| 122 |
+
node test-xsai.js
|
| 123 |
+
```
|
| 124 |
+
|
| 125 |
+
This will test both text generation and streaming with reasoning extraction.
|
| 126 |
+
|
| 127 |
+
### Migration from node-fetch
|
| 128 |
+
|
| 129 |
+
The application has been migrated from using `node-fetch` directly to using xsai's abstraction layer. This provides:
|
| 130 |
+
- Better error handling
|
| 131 |
+
- Consistent API across different model providers
|
| 132 |
+
- Built-in streaming utilities
|
| 133 |
+
- Simplified reasoning extraction
|
XSAI_INTEGRATION_SUMMARY.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# xsai Integration Summary
|
| 2 |
+
|
| 3 |
+
## π― Objective
|
| 4 |
+
Migrated the thinking-model-client from using `node-fetch` directly to using the [xsai](https://github.com/moeru-ai/xsai) library for LLM provider connections.
|
| 5 |
+
|
| 6 |
+
## π Changes Made
|
| 7 |
+
|
| 8 |
+
### 1. Dependencies Updated
|
| 9 |
+
- **Added**:
|
| 10 |
+
- `@xsai/stream-text@^0.3.3` - For streaming text responses
|
| 11 |
+
- `@xsai/generate-text@^0.3.3` - For text generation (summarization)
|
| 12 |
+
- `@xsai/utils-reasoning@^0.3.3` - For extracting reasoning from responses
|
| 13 |
+
- **Removed**:
|
| 14 |
+
- `node-fetch` - No longer needed
|
| 15 |
+
|
| 16 |
+
### 2. Server Implementation (`server/index.js`)
|
| 17 |
+
|
| 18 |
+
#### Chat Endpoint (`/api/chat`)
|
| 19 |
+
- **Before**: Used `node-fetch` with manual streaming setup
|
| 20 |
+
- **After**: Uses `xsai.streamText()` with automatic reasoning extraction
|
| 21 |
+
- **Benefits**:
|
| 22 |
+
- Cleaner error handling
|
| 23 |
+
- Automatic reasoning/content separation
|
| 24 |
+
- Better streaming reliability
|
| 25 |
+
- Built-in support for different model formats
|
| 26 |
+
|
| 27 |
+
#### Summarization Endpoint (`/api/summarize`)
|
| 28 |
+
- **Before**: Used `node-fetch` with manual JSON parsing
|
| 29 |
+
- **After**: Uses `xsai.generateText()` for direct text generation
|
| 30 |
+
- **Benefits**:
|
| 31 |
+
- Simplified API calls
|
| 32 |
+
- Better error handling
|
| 33 |
+
- Consistent interface across providers
|
| 34 |
+
|
| 35 |
+
### 3. Key Features Enhanced
|
| 36 |
+
|
| 37 |
+
#### Reasoning Extraction
|
| 38 |
+
- Automatically extracts `<think>...</think>` tags from AI responses
|
| 39 |
+
- Separates reasoning process from final answer
|
| 40 |
+
- Streams reasoning first, then content for better UX
|
| 41 |
+
|
| 42 |
+
#### Streaming Improvements
|
| 43 |
+
- More reliable streaming with better error handling
|
| 44 |
+
- Consistent format across different model providers
|
| 45 |
+
- Automatic handling of different response formats
|
| 46 |
+
|
| 47 |
+
### 4. Testing & Documentation
|
| 48 |
+
|
| 49 |
+
#### Test Script (`test-xsai.js`)
|
| 50 |
+
- Created comprehensive test script to verify xsai integration
|
| 51 |
+
- Tests both `generateText` and `streamText` with reasoning extraction
|
| 52 |
+
- Provides easy way to validate setup with different API providers
|
| 53 |
+
|
| 54 |
+
#### Documentation Updates
|
| 55 |
+
- Updated README.md with xsai integration details
|
| 56 |
+
- Added technical implementation details
|
| 57 |
+
- Enhanced feature descriptions
|
| 58 |
+
- Updated CHANGELOG.md with breaking changes
|
| 59 |
+
- Version bumped to 0.2.0 (breaking change)
|
| 60 |
+
|
| 61 |
+
## π Benefits of xsai Integration
|
| 62 |
+
|
| 63 |
+
### Performance
|
| 64 |
+
- **Lightweight**: Smaller bundle size compared to multiple HTTP client dependencies
|
| 65 |
+
- **Efficient**: Optimized for AI model interactions
|
| 66 |
+
- **Runtime Agnostic**: Works in Node.js, Deno, Bun, and browsers
|
| 67 |
+
|
| 68 |
+
### Developer Experience
|
| 69 |
+
- **Simplified API**: Consistent interface across different model providers
|
| 70 |
+
- **Better Error Handling**: Built-in error handling and retry logic
|
| 71 |
+
- **Type Safety**: Better TypeScript support for AI interactions
|
| 72 |
+
|
| 73 |
+
### Features
|
| 74 |
+
- **Automatic Reasoning Extraction**: Built-in support for thinking processes
|
| 75 |
+
- **Streaming Utilities**: Advanced streaming capabilities
|
| 76 |
+
- **Multiple Providers**: Easily switch between different AI providers
|
| 77 |
+
|
| 78 |
+
## π§ͺ Testing the Integration
|
| 79 |
+
|
| 80 |
+
1. **Start the server**:
|
| 81 |
+
```bash
|
| 82 |
+
npm run server
|
| 83 |
+
```
|
| 84 |
+
|
| 85 |
+
2. **Test with the frontend**:
|
| 86 |
+
```bash
|
| 87 |
+
npm start
|
| 88 |
+
```
|
| 89 |
+
|
| 90 |
+
3. **Run standalone tests**:
|
| 91 |
+
```bash
|
| 92 |
+
node test-xsai.js
|
| 93 |
+
```
|
| 94 |
+
(After updating API credentials in the test file)
|
| 95 |
+
|
| 96 |
+
## π§ Configuration
|
| 97 |
+
|
| 98 |
+
The application maintains the same configuration interface:
|
| 99 |
+
- API endpoints are automatically converted to xsai's baseURL format
|
| 100 |
+
- All existing profiles and settings continue to work
|
| 101 |
+
- No changes required to existing user configurations
|
| 102 |
+
|
| 103 |
+
## π Migration Notes
|
| 104 |
+
|
| 105 |
+
This is a **breaking change** internally but maintains API compatibility:
|
| 106 |
+
- Server endpoints (`/api/chat`, `/api/summarize`) maintain same interface
|
| 107 |
+
- Frontend code requires no changes
|
| 108 |
+
- User configurations remain compatible
|
| 109 |
+
- Docker deployments work without changes
|
| 110 |
+
|
| 111 |
+
## π Result
|
| 112 |
+
|
| 113 |
+
The thinking-model-client now uses xsai for all LLM interactions, providing:
|
| 114 |
+
- More reliable streaming
|
| 115 |
+
- Better reasoning extraction
|
| 116 |
+
- Cleaner codebase
|
| 117 |
+
- Enhanced error handling
|
| 118 |
+
- Future-proof architecture for AI model connections
|
| 119 |
+
|
| 120 |
+
The migration is complete and fully functional!
|
package-lock.json
CHANGED
|
@@ -1,18 +1,20 @@
|
|
| 1 |
{
|
| 2 |
"name": "thinking-model-client",
|
| 3 |
-
"version": "0.
|
| 4 |
"lockfileVersion": 3,
|
| 5 |
"requires": true,
|
| 6 |
"packages": {
|
| 7 |
"": {
|
| 8 |
"name": "thinking-model-client",
|
| 9 |
-
"version": "0.
|
| 10 |
"dependencies": {
|
| 11 |
"@modelcontextprotocol/sdk": "^1.8.0",
|
|
|
|
|
|
|
|
|
|
| 12 |
"cors": "^2.8.5",
|
| 13 |
"eventsource": "^3.0.6",
|
| 14 |
"express": "^4.18.2",
|
| 15 |
-
"node-fetch": "^3.3.2",
|
| 16 |
"react": "^18.2.0",
|
| 17 |
"react-dom": "^18.2.0",
|
| 18 |
"react-markdown": "^10.0.0",
|
|
@@ -909,17 +911,20 @@
|
|
| 909 |
}
|
| 910 |
},
|
| 911 |
"node_modules/@modelcontextprotocol/sdk": {
|
| 912 |
-
"version": "1.
|
| 913 |
-
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.
|
| 914 |
-
"integrity": "sha512-
|
|
|
|
| 915 |
"dependencies": {
|
|
|
|
| 916 |
"content-type": "^1.0.5",
|
| 917 |
"cors": "^2.8.5",
|
| 918 |
-
"cross-spawn": "^7.0.
|
| 919 |
"eventsource": "^3.0.2",
|
|
|
|
| 920 |
"express": "^5.0.1",
|
| 921 |
"express-rate-limit": "^7.5.0",
|
| 922 |
-
"pkce-challenge": "^
|
| 923 |
"raw-body": "^3.0.0",
|
| 924 |
"zod": "^3.23.8",
|
| 925 |
"zod-to-json-schema": "^3.24.1"
|
|
@@ -932,6 +937,7 @@
|
|
| 932 |
"version": "2.0.0",
|
| 933 |
"resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
|
| 934 |
"integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
|
|
|
|
| 935 |
"dependencies": {
|
| 936 |
"mime-types": "^3.0.0",
|
| 937 |
"negotiator": "^1.0.0"
|
|
@@ -944,6 +950,7 @@
|
|
| 944 |
"version": "2.2.0",
|
| 945 |
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz",
|
| 946 |
"integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==",
|
|
|
|
| 947 |
"dependencies": {
|
| 948 |
"bytes": "^3.1.2",
|
| 949 |
"content-type": "^1.0.5",
|
|
@@ -963,6 +970,7 @@
|
|
| 963 |
"version": "1.0.0",
|
| 964 |
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz",
|
| 965 |
"integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==",
|
|
|
|
| 966 |
"dependencies": {
|
| 967 |
"safe-buffer": "5.2.1"
|
| 968 |
},
|
|
@@ -974,6 +982,7 @@
|
|
| 974 |
"version": "1.2.2",
|
| 975 |
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
|
| 976 |
"integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
|
|
|
|
| 977 |
"engines": {
|
| 978 |
"node": ">=6.6.0"
|
| 979 |
}
|
|
@@ -982,6 +991,7 @@
|
|
| 982 |
"version": "5.1.0",
|
| 983 |
"resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz",
|
| 984 |
"integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==",
|
|
|
|
| 985 |
"dependencies": {
|
| 986 |
"accepts": "^2.0.0",
|
| 987 |
"body-parser": "^2.2.0",
|
|
@@ -1023,6 +1033,7 @@
|
|
| 1023 |
"version": "2.1.0",
|
| 1024 |
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz",
|
| 1025 |
"integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==",
|
|
|
|
| 1026 |
"dependencies": {
|
| 1027 |
"debug": "^4.4.0",
|
| 1028 |
"encodeurl": "^2.0.0",
|
|
@@ -1039,6 +1050,7 @@
|
|
| 1039 |
"version": "2.0.0",
|
| 1040 |
"resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
|
| 1041 |
"integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
|
|
|
|
| 1042 |
"engines": {
|
| 1043 |
"node": ">= 0.8"
|
| 1044 |
}
|
|
@@ -1047,6 +1059,7 @@
|
|
| 1047 |
"version": "0.6.3",
|
| 1048 |
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
| 1049 |
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
|
|
|
| 1050 |
"dependencies": {
|
| 1051 |
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
| 1052 |
},
|
|
@@ -1058,6 +1071,7 @@
|
|
| 1058 |
"version": "1.1.0",
|
| 1059 |
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
|
| 1060 |
"integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
|
|
|
|
| 1061 |
"engines": {
|
| 1062 |
"node": ">= 0.8"
|
| 1063 |
}
|
|
@@ -1066,6 +1080,7 @@
|
|
| 1066 |
"version": "2.0.0",
|
| 1067 |
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
|
| 1068 |
"integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
|
|
|
|
| 1069 |
"engines": {
|
| 1070 |
"node": ">=18"
|
| 1071 |
},
|
|
@@ -1077,6 +1092,7 @@
|
|
| 1077 |
"version": "1.54.0",
|
| 1078 |
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
|
| 1079 |
"integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
|
|
|
|
| 1080 |
"engines": {
|
| 1081 |
"node": ">= 0.6"
|
| 1082 |
}
|
|
@@ -1085,6 +1101,7 @@
|
|
| 1085 |
"version": "3.0.1",
|
| 1086 |
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
|
| 1087 |
"integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
|
|
|
|
| 1088 |
"dependencies": {
|
| 1089 |
"mime-db": "^1.54.0"
|
| 1090 |
},
|
|
@@ -1096,6 +1113,7 @@
|
|
| 1096 |
"version": "1.0.0",
|
| 1097 |
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
|
| 1098 |
"integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
|
|
|
|
| 1099 |
"engines": {
|
| 1100 |
"node": ">= 0.6"
|
| 1101 |
}
|
|
@@ -1104,6 +1122,7 @@
|
|
| 1104 |
"version": "6.14.0",
|
| 1105 |
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
|
| 1106 |
"integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
|
|
|
|
| 1107 |
"dependencies": {
|
| 1108 |
"side-channel": "^1.1.0"
|
| 1109 |
},
|
|
@@ -1118,6 +1137,7 @@
|
|
| 1118 |
"version": "3.0.0",
|
| 1119 |
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz",
|
| 1120 |
"integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==",
|
|
|
|
| 1121 |
"dependencies": {
|
| 1122 |
"bytes": "3.1.2",
|
| 1123 |
"http-errors": "2.0.0",
|
|
@@ -1132,6 +1152,7 @@
|
|
| 1132 |
"version": "1.2.0",
|
| 1133 |
"resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz",
|
| 1134 |
"integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==",
|
|
|
|
| 1135 |
"dependencies": {
|
| 1136 |
"debug": "^4.3.5",
|
| 1137 |
"encodeurl": "^2.0.0",
|
|
@@ -1153,6 +1174,7 @@
|
|
| 1153 |
"version": "2.2.0",
|
| 1154 |
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz",
|
| 1155 |
"integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==",
|
|
|
|
| 1156 |
"dependencies": {
|
| 1157 |
"encodeurl": "^2.0.0",
|
| 1158 |
"escape-html": "^1.0.3",
|
|
@@ -1167,6 +1189,7 @@
|
|
| 1167 |
"version": "2.0.1",
|
| 1168 |
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
|
| 1169 |
"integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
|
|
|
|
| 1170 |
"dependencies": {
|
| 1171 |
"content-type": "^1.0.5",
|
| 1172 |
"media-typer": "^1.1.0",
|
|
@@ -1451,6 +1474,46 @@
|
|
| 1451 |
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0"
|
| 1452 |
}
|
| 1453 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1454 |
"node_modules/accepts": {
|
| 1455 |
"version": "1.3.8",
|
| 1456 |
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
|
@@ -1476,6 +1539,22 @@
|
|
| 1476 |
"node": ">=8"
|
| 1477 |
}
|
| 1478 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1479 |
"node_modules/ansi-colors": {
|
| 1480 |
"version": "4.1.3",
|
| 1481 |
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
|
|
@@ -2462,14 +2541,6 @@
|
|
| 2462 |
"node": ">=0.10"
|
| 2463 |
}
|
| 2464 |
},
|
| 2465 |
-
"node_modules/data-uri-to-buffer": {
|
| 2466 |
-
"version": "4.0.1",
|
| 2467 |
-
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
|
| 2468 |
-
"integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
|
| 2469 |
-
"engines": {
|
| 2470 |
-
"node": ">= 12"
|
| 2471 |
-
}
|
| 2472 |
-
},
|
| 2473 |
"node_modules/date-fns": {
|
| 2474 |
"version": "2.30.0",
|
| 2475 |
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
|
|
@@ -2824,9 +2895,10 @@
|
|
| 2824 |
"dev": true
|
| 2825 |
},
|
| 2826 |
"node_modules/eventsource": {
|
| 2827 |
-
"version": "3.0.
|
| 2828 |
-
"resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.
|
| 2829 |
-
"integrity": "sha512-
|
|
|
|
| 2830 |
"dependencies": {
|
| 2831 |
"eventsource-parser": "^3.0.1"
|
| 2832 |
},
|
|
@@ -2835,11 +2907,12 @@
|
|
| 2835 |
}
|
| 2836 |
},
|
| 2837 |
"node_modules/eventsource-parser": {
|
| 2838 |
-
"version": "3.0.
|
| 2839 |
-
"resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.
|
| 2840 |
-
"integrity": "sha512-
|
|
|
|
| 2841 |
"engines": {
|
| 2842 |
-
"node": ">=
|
| 2843 |
}
|
| 2844 |
},
|
| 2845 |
"node_modules/execa": {
|
|
@@ -2929,9 +3002,10 @@
|
|
| 2929 |
}
|
| 2930 |
},
|
| 2931 |
"node_modules/express-rate-limit": {
|
| 2932 |
-
"version": "7.5.
|
| 2933 |
-
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.
|
| 2934 |
-
"integrity": "sha512-
|
|
|
|
| 2935 |
"engines": {
|
| 2936 |
"node": ">= 16"
|
| 2937 |
},
|
|
@@ -2939,7 +3013,7 @@
|
|
| 2939 |
"url": "https://github.com/sponsors/express-rate-limit"
|
| 2940 |
},
|
| 2941 |
"peerDependencies": {
|
| 2942 |
-
"express": "
|
| 2943 |
}
|
| 2944 |
},
|
| 2945 |
"node_modules/express/node_modules/debug": {
|
|
@@ -2989,6 +3063,12 @@
|
|
| 2989 |
"node >=0.6.0"
|
| 2990 |
]
|
| 2991 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2992 |
"node_modules/fast-glob": {
|
| 2993 |
"version": "3.3.3",
|
| 2994 |
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
|
|
@@ -3017,6 +3097,12 @@
|
|
| 3017 |
"node": ">= 6"
|
| 3018 |
}
|
| 3019 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3020 |
"node_modules/fastq": {
|
| 3021 |
"version": "1.19.1",
|
| 3022 |
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
|
|
@@ -3035,28 +3121,6 @@
|
|
| 3035 |
"pend": "~1.2.0"
|
| 3036 |
}
|
| 3037 |
},
|
| 3038 |
-
"node_modules/fetch-blob": {
|
| 3039 |
-
"version": "3.2.0",
|
| 3040 |
-
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
|
| 3041 |
-
"integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
|
| 3042 |
-
"funding": [
|
| 3043 |
-
{
|
| 3044 |
-
"type": "github",
|
| 3045 |
-
"url": "https://github.com/sponsors/jimmywarting"
|
| 3046 |
-
},
|
| 3047 |
-
{
|
| 3048 |
-
"type": "paypal",
|
| 3049 |
-
"url": "https://paypal.me/jimmywarting"
|
| 3050 |
-
}
|
| 3051 |
-
],
|
| 3052 |
-
"dependencies": {
|
| 3053 |
-
"node-domexception": "^1.0.0",
|
| 3054 |
-
"web-streams-polyfill": "^3.0.3"
|
| 3055 |
-
},
|
| 3056 |
-
"engines": {
|
| 3057 |
-
"node": "^12.20 || >= 14.13"
|
| 3058 |
-
}
|
| 3059 |
-
},
|
| 3060 |
"node_modules/figures": {
|
| 3061 |
"version": "3.2.0",
|
| 3062 |
"resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
|
|
@@ -3174,17 +3238,6 @@
|
|
| 3174 |
"node": ">= 6"
|
| 3175 |
}
|
| 3176 |
},
|
| 3177 |
-
"node_modules/formdata-polyfill": {
|
| 3178 |
-
"version": "4.0.10",
|
| 3179 |
-
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
|
| 3180 |
-
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
|
| 3181 |
-
"dependencies": {
|
| 3182 |
-
"fetch-blob": "^3.1.2"
|
| 3183 |
-
},
|
| 3184 |
-
"engines": {
|
| 3185 |
-
"node": ">=12.20.0"
|
| 3186 |
-
}
|
| 3187 |
-
},
|
| 3188 |
"node_modules/forwarded": {
|
| 3189 |
"version": "0.2.0",
|
| 3190 |
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
|
@@ -3821,7 +3874,8 @@
|
|
| 3821 |
"node_modules/is-promise": {
|
| 3822 |
"version": "4.0.0",
|
| 3823 |
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
|
| 3824 |
-
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="
|
|
|
|
| 3825 |
},
|
| 3826 |
"node_modules/is-stream": {
|
| 3827 |
"version": "2.0.1",
|
|
@@ -3930,6 +3984,12 @@
|
|
| 3930 |
"integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
|
| 3931 |
"dev": true
|
| 3932 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3933 |
"node_modules/json-stringify-safe": {
|
| 3934 |
"version": "5.0.1",
|
| 3935 |
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
|
@@ -5127,41 +5187,6 @@
|
|
| 5127 |
"node": ">= 0.6"
|
| 5128 |
}
|
| 5129 |
},
|
| 5130 |
-
"node_modules/node-domexception": {
|
| 5131 |
-
"version": "1.0.0",
|
| 5132 |
-
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
| 5133 |
-
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
|
| 5134 |
-
"funding": [
|
| 5135 |
-
{
|
| 5136 |
-
"type": "github",
|
| 5137 |
-
"url": "https://github.com/sponsors/jimmywarting"
|
| 5138 |
-
},
|
| 5139 |
-
{
|
| 5140 |
-
"type": "github",
|
| 5141 |
-
"url": "https://paypal.me/jimmywarting"
|
| 5142 |
-
}
|
| 5143 |
-
],
|
| 5144 |
-
"engines": {
|
| 5145 |
-
"node": ">=10.5.0"
|
| 5146 |
-
}
|
| 5147 |
-
},
|
| 5148 |
-
"node_modules/node-fetch": {
|
| 5149 |
-
"version": "3.3.2",
|
| 5150 |
-
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
|
| 5151 |
-
"integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
|
| 5152 |
-
"dependencies": {
|
| 5153 |
-
"data-uri-to-buffer": "^4.0.0",
|
| 5154 |
-
"fetch-blob": "^3.1.4",
|
| 5155 |
-
"formdata-polyfill": "^4.0.10"
|
| 5156 |
-
},
|
| 5157 |
-
"engines": {
|
| 5158 |
-
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
| 5159 |
-
},
|
| 5160 |
-
"funding": {
|
| 5161 |
-
"type": "opencollective",
|
| 5162 |
-
"url": "https://opencollective.com/node-fetch"
|
| 5163 |
-
}
|
| 5164 |
-
},
|
| 5165 |
"node_modules/node-releases": {
|
| 5166 |
"version": "2.0.19",
|
| 5167 |
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
|
|
@@ -5426,9 +5451,10 @@
|
|
| 5426 |
}
|
| 5427 |
},
|
| 5428 |
"node_modules/pkce-challenge": {
|
| 5429 |
-
"version": "
|
| 5430 |
-
"resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-
|
| 5431 |
-
"integrity": "sha512-
|
|
|
|
| 5432 |
"engines": {
|
| 5433 |
"node": ">=16.20.0"
|
| 5434 |
}
|
|
@@ -5700,6 +5726,15 @@
|
|
| 5700 |
"once": "^1.3.1"
|
| 5701 |
}
|
| 5702 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5703 |
"node_modules/qs": {
|
| 5704 |
"version": "6.13.0",
|
| 5705 |
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
|
|
@@ -5977,6 +6012,7 @@
|
|
| 5977 |
"version": "2.2.0",
|
| 5978 |
"resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
|
| 5979 |
"integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
|
|
|
|
| 5980 |
"dependencies": {
|
| 5981 |
"debug": "^4.4.0",
|
| 5982 |
"depd": "^2.0.0",
|
|
@@ -5992,6 +6028,7 @@
|
|
| 5992 |
"version": "8.2.0",
|
| 5993 |
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz",
|
| 5994 |
"integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==",
|
|
|
|
| 5995 |
"engines": {
|
| 5996 |
"node": ">=16"
|
| 5997 |
}
|
|
@@ -6917,6 +6954,15 @@
|
|
| 6917 |
"browserslist": ">= 4.21.0"
|
| 6918 |
}
|
| 6919 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6920 |
"node_modules/url-join": {
|
| 6921 |
"version": "4.0.1",
|
| 6922 |
"resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
|
|
@@ -7068,14 +7114,6 @@
|
|
| 7068 |
"node": ">=12.0.0"
|
| 7069 |
}
|
| 7070 |
},
|
| 7071 |
-
"node_modules/web-streams-polyfill": {
|
| 7072 |
-
"version": "3.3.3",
|
| 7073 |
-
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
|
| 7074 |
-
"integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
|
| 7075 |
-
"engines": {
|
| 7076 |
-
"node": ">= 8"
|
| 7077 |
-
}
|
| 7078 |
-
},
|
| 7079 |
"node_modules/whatwg-encoding": {
|
| 7080 |
"version": "2.0.0",
|
| 7081 |
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
|
|
@@ -7219,17 +7257,19 @@
|
|
| 7219 |
}
|
| 7220 |
},
|
| 7221 |
"node_modules/zod": {
|
| 7222 |
-
"version": "3.
|
| 7223 |
-
"resolved": "https://registry.npmjs.org/zod/-/zod-3.
|
| 7224 |
-
"integrity": "sha512-
|
|
|
|
| 7225 |
"funding": {
|
| 7226 |
"url": "https://github.com/sponsors/colinhacks"
|
| 7227 |
}
|
| 7228 |
},
|
| 7229 |
"node_modules/zod-to-json-schema": {
|
| 7230 |
-
"version": "3.24.
|
| 7231 |
-
"resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.
|
| 7232 |
-
"integrity": "sha512
|
|
|
|
| 7233 |
"peerDependencies": {
|
| 7234 |
"zod": "^3.24.1"
|
| 7235 |
}
|
|
|
|
| 1 |
{
|
| 2 |
"name": "thinking-model-client",
|
| 3 |
+
"version": "0.2.0",
|
| 4 |
"lockfileVersion": 3,
|
| 5 |
"requires": true,
|
| 6 |
"packages": {
|
| 7 |
"": {
|
| 8 |
"name": "thinking-model-client",
|
| 9 |
+
"version": "0.2.0",
|
| 10 |
"dependencies": {
|
| 11 |
"@modelcontextprotocol/sdk": "^1.8.0",
|
| 12 |
+
"@xsai/generate-text": "^0.3.3",
|
| 13 |
+
"@xsai/stream-text": "^0.3.3",
|
| 14 |
+
"@xsai/utils-reasoning": "^0.3.3",
|
| 15 |
"cors": "^2.8.5",
|
| 16 |
"eventsource": "^3.0.6",
|
| 17 |
"express": "^4.18.2",
|
|
|
|
| 18 |
"react": "^18.2.0",
|
| 19 |
"react-dom": "^18.2.0",
|
| 20 |
"react-markdown": "^10.0.0",
|
|
|
|
| 911 |
}
|
| 912 |
},
|
| 913 |
"node_modules/@modelcontextprotocol/sdk": {
|
| 914 |
+
"version": "1.17.0",
|
| 915 |
+
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.17.0.tgz",
|
| 916 |
+
"integrity": "sha512-qFfbWFA7r1Sd8D697L7GkTd36yqDuTkvz0KfOGkgXR8EUhQn3/EDNIR/qUdQNMT8IjmasBvHWuXeisxtXTQT2g==",
|
| 917 |
+
"license": "MIT",
|
| 918 |
"dependencies": {
|
| 919 |
+
"ajv": "^6.12.6",
|
| 920 |
"content-type": "^1.0.5",
|
| 921 |
"cors": "^2.8.5",
|
| 922 |
+
"cross-spawn": "^7.0.5",
|
| 923 |
"eventsource": "^3.0.2",
|
| 924 |
+
"eventsource-parser": "^3.0.0",
|
| 925 |
"express": "^5.0.1",
|
| 926 |
"express-rate-limit": "^7.5.0",
|
| 927 |
+
"pkce-challenge": "^5.0.0",
|
| 928 |
"raw-body": "^3.0.0",
|
| 929 |
"zod": "^3.23.8",
|
| 930 |
"zod-to-json-schema": "^3.24.1"
|
|
|
|
| 937 |
"version": "2.0.0",
|
| 938 |
"resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
|
| 939 |
"integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
|
| 940 |
+
"license": "MIT",
|
| 941 |
"dependencies": {
|
| 942 |
"mime-types": "^3.0.0",
|
| 943 |
"negotiator": "^1.0.0"
|
|
|
|
| 950 |
"version": "2.2.0",
|
| 951 |
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz",
|
| 952 |
"integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==",
|
| 953 |
+
"license": "MIT",
|
| 954 |
"dependencies": {
|
| 955 |
"bytes": "^3.1.2",
|
| 956 |
"content-type": "^1.0.5",
|
|
|
|
| 970 |
"version": "1.0.0",
|
| 971 |
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz",
|
| 972 |
"integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==",
|
| 973 |
+
"license": "MIT",
|
| 974 |
"dependencies": {
|
| 975 |
"safe-buffer": "5.2.1"
|
| 976 |
},
|
|
|
|
| 982 |
"version": "1.2.2",
|
| 983 |
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
|
| 984 |
"integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
|
| 985 |
+
"license": "MIT",
|
| 986 |
"engines": {
|
| 987 |
"node": ">=6.6.0"
|
| 988 |
}
|
|
|
|
| 991 |
"version": "5.1.0",
|
| 992 |
"resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz",
|
| 993 |
"integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==",
|
| 994 |
+
"license": "MIT",
|
| 995 |
"dependencies": {
|
| 996 |
"accepts": "^2.0.0",
|
| 997 |
"body-parser": "^2.2.0",
|
|
|
|
| 1033 |
"version": "2.1.0",
|
| 1034 |
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz",
|
| 1035 |
"integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==",
|
| 1036 |
+
"license": "MIT",
|
| 1037 |
"dependencies": {
|
| 1038 |
"debug": "^4.4.0",
|
| 1039 |
"encodeurl": "^2.0.0",
|
|
|
|
| 1050 |
"version": "2.0.0",
|
| 1051 |
"resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
|
| 1052 |
"integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
|
| 1053 |
+
"license": "MIT",
|
| 1054 |
"engines": {
|
| 1055 |
"node": ">= 0.8"
|
| 1056 |
}
|
|
|
|
| 1059 |
"version": "0.6.3",
|
| 1060 |
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
| 1061 |
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
| 1062 |
+
"license": "MIT",
|
| 1063 |
"dependencies": {
|
| 1064 |
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
| 1065 |
},
|
|
|
|
| 1071 |
"version": "1.1.0",
|
| 1072 |
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
|
| 1073 |
"integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
|
| 1074 |
+
"license": "MIT",
|
| 1075 |
"engines": {
|
| 1076 |
"node": ">= 0.8"
|
| 1077 |
}
|
|
|
|
| 1080 |
"version": "2.0.0",
|
| 1081 |
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
|
| 1082 |
"integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
|
| 1083 |
+
"license": "MIT",
|
| 1084 |
"engines": {
|
| 1085 |
"node": ">=18"
|
| 1086 |
},
|
|
|
|
| 1092 |
"version": "1.54.0",
|
| 1093 |
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
|
| 1094 |
"integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
|
| 1095 |
+
"license": "MIT",
|
| 1096 |
"engines": {
|
| 1097 |
"node": ">= 0.6"
|
| 1098 |
}
|
|
|
|
| 1101 |
"version": "3.0.1",
|
| 1102 |
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
|
| 1103 |
"integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
|
| 1104 |
+
"license": "MIT",
|
| 1105 |
"dependencies": {
|
| 1106 |
"mime-db": "^1.54.0"
|
| 1107 |
},
|
|
|
|
| 1113 |
"version": "1.0.0",
|
| 1114 |
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
|
| 1115 |
"integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
|
| 1116 |
+
"license": "MIT",
|
| 1117 |
"engines": {
|
| 1118 |
"node": ">= 0.6"
|
| 1119 |
}
|
|
|
|
| 1122 |
"version": "6.14.0",
|
| 1123 |
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
|
| 1124 |
"integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
|
| 1125 |
+
"license": "BSD-3-Clause",
|
| 1126 |
"dependencies": {
|
| 1127 |
"side-channel": "^1.1.0"
|
| 1128 |
},
|
|
|
|
| 1137 |
"version": "3.0.0",
|
| 1138 |
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz",
|
| 1139 |
"integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==",
|
| 1140 |
+
"license": "MIT",
|
| 1141 |
"dependencies": {
|
| 1142 |
"bytes": "3.1.2",
|
| 1143 |
"http-errors": "2.0.0",
|
|
|
|
| 1152 |
"version": "1.2.0",
|
| 1153 |
"resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz",
|
| 1154 |
"integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==",
|
| 1155 |
+
"license": "MIT",
|
| 1156 |
"dependencies": {
|
| 1157 |
"debug": "^4.3.5",
|
| 1158 |
"encodeurl": "^2.0.0",
|
|
|
|
| 1174 |
"version": "2.2.0",
|
| 1175 |
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz",
|
| 1176 |
"integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==",
|
| 1177 |
+
"license": "MIT",
|
| 1178 |
"dependencies": {
|
| 1179 |
"encodeurl": "^2.0.0",
|
| 1180 |
"escape-html": "^1.0.3",
|
|
|
|
| 1189 |
"version": "2.0.1",
|
| 1190 |
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
|
| 1191 |
"integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
|
| 1192 |
+
"license": "MIT",
|
| 1193 |
"dependencies": {
|
| 1194 |
"content-type": "^1.0.5",
|
| 1195 |
"media-typer": "^1.1.0",
|
|
|
|
| 1474 |
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0"
|
| 1475 |
}
|
| 1476 |
},
|
| 1477 |
+
"node_modules/@xsai/generate-text": {
|
| 1478 |
+
"version": "0.3.3",
|
| 1479 |
+
"resolved": "https://registry.npmjs.org/@xsai/generate-text/-/generate-text-0.3.3.tgz",
|
| 1480 |
+
"integrity": "sha512-lVaUzbIgGOdsbKUm5p1ftSYteq3tMCismodY7tK+MEOlaEErmSeS+SRLZmz6X2Jn23ZuYsrj1gbGqdTciBjgHg==",
|
| 1481 |
+
"license": "MIT",
|
| 1482 |
+
"dependencies": {
|
| 1483 |
+
"@xsai/shared": "~0.3.3",
|
| 1484 |
+
"@xsai/shared-chat": "~0.3.3"
|
| 1485 |
+
}
|
| 1486 |
+
},
|
| 1487 |
+
"node_modules/@xsai/shared": {
|
| 1488 |
+
"version": "0.3.3",
|
| 1489 |
+
"resolved": "https://registry.npmjs.org/@xsai/shared/-/shared-0.3.3.tgz",
|
| 1490 |
+
"integrity": "sha512-1xul8h7He5cM+H/gGx8pdE/LLqujO3xSHM2+V4XVEjI05VxQq+s5lk42/7NUUbjcvcFxi5Ow9IL4pezHgxq9aQ==",
|
| 1491 |
+
"license": "MIT"
|
| 1492 |
+
},
|
| 1493 |
+
"node_modules/@xsai/shared-chat": {
|
| 1494 |
+
"version": "0.3.3",
|
| 1495 |
+
"resolved": "https://registry.npmjs.org/@xsai/shared-chat/-/shared-chat-0.3.3.tgz",
|
| 1496 |
+
"integrity": "sha512-zCfAlXhNfQ3+ErhP8BnSIdsELAENHubfscLdImls+9zNHfY1AzIaBuRIf5dWJYmC4/NsOop1QHYjfM+7Wg4gjw==",
|
| 1497 |
+
"license": "MIT",
|
| 1498 |
+
"dependencies": {
|
| 1499 |
+
"@xsai/shared": "~0.3.3"
|
| 1500 |
+
}
|
| 1501 |
+
},
|
| 1502 |
+
"node_modules/@xsai/stream-text": {
|
| 1503 |
+
"version": "0.3.3",
|
| 1504 |
+
"resolved": "https://registry.npmjs.org/@xsai/stream-text/-/stream-text-0.3.3.tgz",
|
| 1505 |
+
"integrity": "sha512-Y/f4EkvWIF6nJ/07RJpneAugMV6pHiDi1c0X2pn6m6NhGodpj1HZKzvYTFryW/ZYc5NCG+B7AXUQyCy8PUSOeg==",
|
| 1506 |
+
"license": "MIT",
|
| 1507 |
+
"dependencies": {
|
| 1508 |
+
"@xsai/shared-chat": "~0.3.3"
|
| 1509 |
+
}
|
| 1510 |
+
},
|
| 1511 |
+
"node_modules/@xsai/utils-reasoning": {
|
| 1512 |
+
"version": "0.3.3",
|
| 1513 |
+
"resolved": "https://registry.npmjs.org/@xsai/utils-reasoning/-/utils-reasoning-0.3.3.tgz",
|
| 1514 |
+
"integrity": "sha512-4YiikRMij9ns9I2qEZeyHrG3SSfghfxMJU4DpvNdmZznDT3OujUMHrgD3BuvWXTyuGuyAyV8ZiZ0TR+DXl/Rkg==",
|
| 1515 |
+
"license": "MIT"
|
| 1516 |
+
},
|
| 1517 |
"node_modules/accepts": {
|
| 1518 |
"version": "1.3.8",
|
| 1519 |
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
|
|
|
| 1539 |
"node": ">=8"
|
| 1540 |
}
|
| 1541 |
},
|
| 1542 |
+
"node_modules/ajv": {
|
| 1543 |
+
"version": "6.12.6",
|
| 1544 |
+
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
| 1545 |
+
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
| 1546 |
+
"license": "MIT",
|
| 1547 |
+
"dependencies": {
|
| 1548 |
+
"fast-deep-equal": "^3.1.1",
|
| 1549 |
+
"fast-json-stable-stringify": "^2.0.0",
|
| 1550 |
+
"json-schema-traverse": "^0.4.1",
|
| 1551 |
+
"uri-js": "^4.2.2"
|
| 1552 |
+
},
|
| 1553 |
+
"funding": {
|
| 1554 |
+
"type": "github",
|
| 1555 |
+
"url": "https://github.com/sponsors/epoberezkin"
|
| 1556 |
+
}
|
| 1557 |
+
},
|
| 1558 |
"node_modules/ansi-colors": {
|
| 1559 |
"version": "4.1.3",
|
| 1560 |
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
|
|
|
|
| 2541 |
"node": ">=0.10"
|
| 2542 |
}
|
| 2543 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2544 |
"node_modules/date-fns": {
|
| 2545 |
"version": "2.30.0",
|
| 2546 |
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
|
|
|
|
| 2895 |
"dev": true
|
| 2896 |
},
|
| 2897 |
"node_modules/eventsource": {
|
| 2898 |
+
"version": "3.0.7",
|
| 2899 |
+
"resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz",
|
| 2900 |
+
"integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==",
|
| 2901 |
+
"license": "MIT",
|
| 2902 |
"dependencies": {
|
| 2903 |
"eventsource-parser": "^3.0.1"
|
| 2904 |
},
|
|
|
|
| 2907 |
}
|
| 2908 |
},
|
| 2909 |
"node_modules/eventsource-parser": {
|
| 2910 |
+
"version": "3.0.3",
|
| 2911 |
+
"resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.3.tgz",
|
| 2912 |
+
"integrity": "sha512-nVpZkTMM9rF6AQ9gPJpFsNAMt48wIzB5TQgiTLdHiuO8XEDhUgZEhqKlZWXbIzo9VmJ/HvysHqEaVeD5v9TPvA==",
|
| 2913 |
+
"license": "MIT",
|
| 2914 |
"engines": {
|
| 2915 |
+
"node": ">=20.0.0"
|
| 2916 |
}
|
| 2917 |
},
|
| 2918 |
"node_modules/execa": {
|
|
|
|
| 3002 |
}
|
| 3003 |
},
|
| 3004 |
"node_modules/express-rate-limit": {
|
| 3005 |
+
"version": "7.5.1",
|
| 3006 |
+
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.1.tgz",
|
| 3007 |
+
"integrity": "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==",
|
| 3008 |
+
"license": "MIT",
|
| 3009 |
"engines": {
|
| 3010 |
"node": ">= 16"
|
| 3011 |
},
|
|
|
|
| 3013 |
"url": "https://github.com/sponsors/express-rate-limit"
|
| 3014 |
},
|
| 3015 |
"peerDependencies": {
|
| 3016 |
+
"express": ">= 4.11"
|
| 3017 |
}
|
| 3018 |
},
|
| 3019 |
"node_modules/express/node_modules/debug": {
|
|
|
|
| 3063 |
"node >=0.6.0"
|
| 3064 |
]
|
| 3065 |
},
|
| 3066 |
+
"node_modules/fast-deep-equal": {
|
| 3067 |
+
"version": "3.1.3",
|
| 3068 |
+
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
| 3069 |
+
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
| 3070 |
+
"license": "MIT"
|
| 3071 |
+
},
|
| 3072 |
"node_modules/fast-glob": {
|
| 3073 |
"version": "3.3.3",
|
| 3074 |
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
|
|
|
|
| 3097 |
"node": ">= 6"
|
| 3098 |
}
|
| 3099 |
},
|
| 3100 |
+
"node_modules/fast-json-stable-stringify": {
|
| 3101 |
+
"version": "2.1.0",
|
| 3102 |
+
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
| 3103 |
+
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
| 3104 |
+
"license": "MIT"
|
| 3105 |
+
},
|
| 3106 |
"node_modules/fastq": {
|
| 3107 |
"version": "1.19.1",
|
| 3108 |
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
|
|
|
|
| 3121 |
"pend": "~1.2.0"
|
| 3122 |
}
|
| 3123 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3124 |
"node_modules/figures": {
|
| 3125 |
"version": "3.2.0",
|
| 3126 |
"resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
|
|
|
|
| 3238 |
"node": ">= 6"
|
| 3239 |
}
|
| 3240 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3241 |
"node_modules/forwarded": {
|
| 3242 |
"version": "0.2.0",
|
| 3243 |
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
|
|
|
| 3874 |
"node_modules/is-promise": {
|
| 3875 |
"version": "4.0.0",
|
| 3876 |
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
|
| 3877 |
+
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
|
| 3878 |
+
"license": "MIT"
|
| 3879 |
},
|
| 3880 |
"node_modules/is-stream": {
|
| 3881 |
"version": "2.0.1",
|
|
|
|
| 3984 |
"integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
|
| 3985 |
"dev": true
|
| 3986 |
},
|
| 3987 |
+
"node_modules/json-schema-traverse": {
|
| 3988 |
+
"version": "0.4.1",
|
| 3989 |
+
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
| 3990 |
+
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
| 3991 |
+
"license": "MIT"
|
| 3992 |
+
},
|
| 3993 |
"node_modules/json-stringify-safe": {
|
| 3994 |
"version": "5.0.1",
|
| 3995 |
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
|
|
|
| 5187 |
"node": ">= 0.6"
|
| 5188 |
}
|
| 5189 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5190 |
"node_modules/node-releases": {
|
| 5191 |
"version": "2.0.19",
|
| 5192 |
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
|
|
|
|
| 5451 |
}
|
| 5452 |
},
|
| 5453 |
"node_modules/pkce-challenge": {
|
| 5454 |
+
"version": "5.0.0",
|
| 5455 |
+
"resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz",
|
| 5456 |
+
"integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==",
|
| 5457 |
+
"license": "MIT",
|
| 5458 |
"engines": {
|
| 5459 |
"node": ">=16.20.0"
|
| 5460 |
}
|
|
|
|
| 5726 |
"once": "^1.3.1"
|
| 5727 |
}
|
| 5728 |
},
|
| 5729 |
+
"node_modules/punycode": {
|
| 5730 |
+
"version": "2.3.1",
|
| 5731 |
+
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
| 5732 |
+
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
| 5733 |
+
"license": "MIT",
|
| 5734 |
+
"engines": {
|
| 5735 |
+
"node": ">=6"
|
| 5736 |
+
}
|
| 5737 |
+
},
|
| 5738 |
"node_modules/qs": {
|
| 5739 |
"version": "6.13.0",
|
| 5740 |
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
|
|
|
|
| 6012 |
"version": "2.2.0",
|
| 6013 |
"resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
|
| 6014 |
"integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
|
| 6015 |
+
"license": "MIT",
|
| 6016 |
"dependencies": {
|
| 6017 |
"debug": "^4.4.0",
|
| 6018 |
"depd": "^2.0.0",
|
|
|
|
| 6028 |
"version": "8.2.0",
|
| 6029 |
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz",
|
| 6030 |
"integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==",
|
| 6031 |
+
"license": "MIT",
|
| 6032 |
"engines": {
|
| 6033 |
"node": ">=16"
|
| 6034 |
}
|
|
|
|
| 6954 |
"browserslist": ">= 4.21.0"
|
| 6955 |
}
|
| 6956 |
},
|
| 6957 |
+
"node_modules/uri-js": {
|
| 6958 |
+
"version": "4.4.1",
|
| 6959 |
+
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
| 6960 |
+
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
| 6961 |
+
"license": "BSD-2-Clause",
|
| 6962 |
+
"dependencies": {
|
| 6963 |
+
"punycode": "^2.1.0"
|
| 6964 |
+
}
|
| 6965 |
+
},
|
| 6966 |
"node_modules/url-join": {
|
| 6967 |
"version": "4.0.1",
|
| 6968 |
"resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
|
|
|
|
| 7114 |
"node": ">=12.0.0"
|
| 7115 |
}
|
| 7116 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7117 |
"node_modules/whatwg-encoding": {
|
| 7118 |
"version": "2.0.0",
|
| 7119 |
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
|
|
|
|
| 7257 |
}
|
| 7258 |
},
|
| 7259 |
"node_modules/zod": {
|
| 7260 |
+
"version": "3.25.76",
|
| 7261 |
+
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
| 7262 |
+
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
|
| 7263 |
+
"license": "MIT",
|
| 7264 |
"funding": {
|
| 7265 |
"url": "https://github.com/sponsors/colinhacks"
|
| 7266 |
}
|
| 7267 |
},
|
| 7268 |
"node_modules/zod-to-json-schema": {
|
| 7269 |
+
"version": "3.24.6",
|
| 7270 |
+
"resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz",
|
| 7271 |
+
"integrity": "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==",
|
| 7272 |
+
"license": "ISC",
|
| 7273 |
"peerDependencies": {
|
| 7274 |
"zod": "^3.24.1"
|
| 7275 |
}
|
package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
{
|
| 2 |
"name": "thinking-model-client",
|
| 3 |
"private": true,
|
| 4 |
-
"version": "0.
|
| 5 |
"type": "module",
|
| 6 |
"scripts": {
|
| 7 |
"dev": "vite",
|
|
@@ -19,10 +19,12 @@
|
|
| 19 |
},
|
| 20 |
"dependencies": {
|
| 21 |
"@modelcontextprotocol/sdk": "^1.8.0",
|
|
|
|
|
|
|
|
|
|
| 22 |
"cors": "^2.8.5",
|
| 23 |
"eventsource": "^3.0.6",
|
| 24 |
"express": "^4.18.2",
|
| 25 |
-
"node-fetch": "^3.3.2",
|
| 26 |
"react": "^18.2.0",
|
| 27 |
"react-dom": "^18.2.0",
|
| 28 |
"react-markdown": "^10.0.0",
|
|
|
|
| 1 |
{
|
| 2 |
"name": "thinking-model-client",
|
| 3 |
"private": true,
|
| 4 |
+
"version": "0.2.0",
|
| 5 |
"type": "module",
|
| 6 |
"scripts": {
|
| 7 |
"dev": "vite",
|
|
|
|
| 19 |
},
|
| 20 |
"dependencies": {
|
| 21 |
"@modelcontextprotocol/sdk": "^1.8.0",
|
| 22 |
+
"@xsai/generate-text": "^0.3.3",
|
| 23 |
+
"@xsai/stream-text": "^0.3.3",
|
| 24 |
+
"@xsai/utils-reasoning": "^0.3.3",
|
| 25 |
"cors": "^2.8.5",
|
| 26 |
"eventsource": "^3.0.6",
|
| 27 |
"express": "^4.18.2",
|
|
|
|
| 28 |
"react": "^18.2.0",
|
| 29 |
"react-dom": "^18.2.0",
|
| 30 |
"react-markdown": "^10.0.0",
|
server/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
| 1 |
import express from 'express';
|
| 2 |
import cors from 'cors';
|
| 3 |
-
import fetch from 'node-fetch';
|
| 4 |
import path from 'path'
|
| 5 |
import { fileURLToPath } from 'url'
|
|
|
|
|
|
|
|
|
|
| 6 |
import { callMcpServer, discoverMcpServerTools, executeMcpTool } from './mcp.js';
|
| 7 |
import {
|
| 8 |
getAvailableMcpServers,
|
|
@@ -31,44 +33,29 @@ app.post('/api/summarize', async (req, res) => {
|
|
| 31 |
});
|
| 32 |
|
| 33 |
try {
|
| 34 |
-
let
|
| 35 |
if (apiEndpoint.endsWith('#')) {
|
| 36 |
-
|
| 37 |
} else if (apiEndpoint.endsWith('/')) {
|
| 38 |
-
|
| 39 |
} else {
|
| 40 |
-
|
| 41 |
}
|
| 42 |
-
console.log('Calling API
|
| 43 |
-
|
| 44 |
-
const
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
content: `Summarize this conversation in 3-5 words: ${content}`
|
| 55 |
-
}],
|
| 56 |
-
temperature: 0.2,
|
| 57 |
-
max_tokens: 20
|
| 58 |
-
})
|
| 59 |
});
|
| 60 |
|
| 61 |
-
|
| 62 |
-
const errorData = await response.text();
|
| 63 |
-
console.error('API error:', {
|
| 64 |
-
status: response.status,
|
| 65 |
-
error: errorData
|
| 66 |
-
});
|
| 67 |
-
throw new Error(`API error: ${response.status} - ${errorData}`);
|
| 68 |
-
}
|
| 69 |
-
|
| 70 |
-
const data = await response.json();
|
| 71 |
-
const summary = data.choices[0].message.content.trim();
|
| 72 |
res.json({ summary });
|
| 73 |
} catch (error) {
|
| 74 |
console.error('Error:', error);
|
|
@@ -86,40 +73,26 @@ app.post('/api/chat', async (req, res) => {
|
|
| 86 |
});
|
| 87 |
|
| 88 |
try {
|
| 89 |
-
let
|
| 90 |
if (apiEndpoint.endsWith('#')) {
|
| 91 |
-
|
| 92 |
} else if (apiEndpoint.endsWith('/')) {
|
| 93 |
-
|
| 94 |
} else {
|
| 95 |
-
|
| 96 |
}
|
| 97 |
-
console.log('Calling API
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
body: JSON.stringify({
|
| 106 |
-
model: model,
|
| 107 |
-
messages: messages,
|
| 108 |
-
stream: true
|
| 109 |
-
})
|
| 110 |
});
|
| 111 |
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
if (!response.ok) {
|
| 116 |
-
const errorData = await response.text();
|
| 117 |
-
console.error('API error:', {
|
| 118 |
-
status: response.status,
|
| 119 |
-
error: errorData
|
| 120 |
-
});
|
| 121 |
-
throw new Error(`API error: ${response.status} - ${errorData}`);
|
| 122 |
-
}
|
| 123 |
|
| 124 |
// Set headers for streaming
|
| 125 |
res.setHeader('Content-Type', 'text/event-stream');
|
|
@@ -133,16 +106,71 @@ app.post('/api/chat', async (req, res) => {
|
|
| 133 |
'Connection': 'keep-alive'
|
| 134 |
});
|
| 135 |
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
|
|
|
| 142 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 143 |
} catch (error) {
|
| 144 |
console.error('Error:', error);
|
| 145 |
-
res.
|
|
|
|
|
|
|
| 146 |
}
|
| 147 |
});
|
| 148 |
|
|
|
|
| 1 |
import express from 'express';
|
| 2 |
import cors from 'cors';
|
|
|
|
| 3 |
import path from 'path'
|
| 4 |
import { fileURLToPath } from 'url'
|
| 5 |
+
import { streamText } from '@xsai/stream-text';
|
| 6 |
+
import { generateText } from '@xsai/generate-text';
|
| 7 |
+
import { extractReasoningStream } from '@xsai/utils-reasoning';
|
| 8 |
import { callMcpServer, discoverMcpServerTools, executeMcpTool } from './mcp.js';
|
| 9 |
import {
|
| 10 |
getAvailableMcpServers,
|
|
|
|
| 33 |
});
|
| 34 |
|
| 35 |
try {
|
| 36 |
+
let baseURL;
|
| 37 |
if (apiEndpoint.endsWith('#')) {
|
| 38 |
+
baseURL = apiEndpoint.slice(0, -1);
|
| 39 |
} else if (apiEndpoint.endsWith('/')) {
|
| 40 |
+
baseURL = `${apiEndpoint}v1`;
|
| 41 |
} else {
|
| 42 |
+
baseURL = `${apiEndpoint}/v1`;
|
| 43 |
}
|
| 44 |
+
console.log('Calling API baseURL:', baseURL);
|
| 45 |
+
|
| 46 |
+
const { text } = await generateText({
|
| 47 |
+
apiKey: apiKey,
|
| 48 |
+
baseURL: baseURL,
|
| 49 |
+
model: model,
|
| 50 |
+
messages: [{
|
| 51 |
+
role: 'user',
|
| 52 |
+
content: `Summarize this conversation in 3-5 words: ${content}`
|
| 53 |
+
}],
|
| 54 |
+
temperature: 0.2,
|
| 55 |
+
max_tokens: 20
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
});
|
| 57 |
|
| 58 |
+
const summary = text.trim();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
res.json({ summary });
|
| 60 |
} catch (error) {
|
| 61 |
console.error('Error:', error);
|
|
|
|
| 73 |
});
|
| 74 |
|
| 75 |
try {
|
| 76 |
+
let baseURL;
|
| 77 |
if (apiEndpoint.endsWith('#')) {
|
| 78 |
+
baseURL = apiEndpoint.slice(0, -1);
|
| 79 |
} else if (apiEndpoint.endsWith('/')) {
|
| 80 |
+
baseURL = `${apiEndpoint}v1`;
|
| 81 |
} else {
|
| 82 |
+
baseURL = `${apiEndpoint}/v1`;
|
| 83 |
}
|
| 84 |
+
console.log('Calling API baseURL:', baseURL);
|
| 85 |
+
|
| 86 |
+
// Use xsai to stream text from the AI model
|
| 87 |
+
const { textStream } = await streamText({
|
| 88 |
+
apiKey: apiKey,
|
| 89 |
+
baseURL: baseURL,
|
| 90 |
+
model: model,
|
| 91 |
+
messages: messages
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 92 |
});
|
| 93 |
|
| 94 |
+
// Extract reasoning and content streams
|
| 95 |
+
const { reasoningStream, textStream: contentStream } = extractReasoningStream(textStream);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
|
| 97 |
// Set headers for streaming
|
| 98 |
res.setHeader('Content-Type', 'text/event-stream');
|
|
|
|
| 106 |
'Connection': 'keep-alive'
|
| 107 |
});
|
| 108 |
|
| 109 |
+
let reasoningText = '';
|
| 110 |
+
let contentText = '';
|
| 111 |
+
let isReasoningComplete = false;
|
| 112 |
+
|
| 113 |
+
// Handle client disconnect
|
| 114 |
+
req.on('close', () => {
|
| 115 |
+
console.log('Client disconnected');
|
| 116 |
});
|
| 117 |
+
|
| 118 |
+
try {
|
| 119 |
+
// First, collect all reasoning
|
| 120 |
+
console.log('Collecting reasoning...');
|
| 121 |
+
for await (const chunk of reasoningStream) {
|
| 122 |
+
reasoningText += chunk;
|
| 123 |
+
}
|
| 124 |
+
isReasoningComplete = true;
|
| 125 |
+
console.log('Reasoning collection complete');
|
| 126 |
+
|
| 127 |
+
// If we have reasoning, send it first wrapped in think tags
|
| 128 |
+
if (reasoningText.trim()) {
|
| 129 |
+
const thinkingChunk = {
|
| 130 |
+
choices: [{
|
| 131 |
+
delta: {
|
| 132 |
+
content: `<think>${reasoningText}</think>`
|
| 133 |
+
}
|
| 134 |
+
}]
|
| 135 |
+
};
|
| 136 |
+
res.write(`data: ${JSON.stringify(thinkingChunk)}\n\n`);
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
// Then stream the content
|
| 140 |
+
console.log('Starting content stream...');
|
| 141 |
+
for await (const chunk of contentStream) {
|
| 142 |
+
if (res.destroyed) break;
|
| 143 |
+
|
| 144 |
+
const responseChunk = {
|
| 145 |
+
choices: [{
|
| 146 |
+
delta: {
|
| 147 |
+
content: chunk
|
| 148 |
+
}
|
| 149 |
+
}]
|
| 150 |
+
};
|
| 151 |
+
|
| 152 |
+
res.write(`data: ${JSON.stringify(responseChunk)}\n\n`);
|
| 153 |
+
contentText += chunk;
|
| 154 |
+
}
|
| 155 |
+
|
| 156 |
+
// Send completion marker
|
| 157 |
+
res.write('data: [DONE]\n\n');
|
| 158 |
+
res.end();
|
| 159 |
+
console.log('Stream completed successfully');
|
| 160 |
+
|
| 161 |
+
} catch (streamError) {
|
| 162 |
+
console.error('Streaming error:', streamError);
|
| 163 |
+
if (!res.destroyed) {
|
| 164 |
+
res.write(`data: ${JSON.stringify({ error: streamError.message })}\n\n`);
|
| 165 |
+
res.end();
|
| 166 |
+
}
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
} catch (error) {
|
| 170 |
console.error('Error:', error);
|
| 171 |
+
if (!res.destroyed) {
|
| 172 |
+
res.status(500).json({ error: error.message });
|
| 173 |
+
}
|
| 174 |
}
|
| 175 |
});
|
| 176 |
|
src/App.jsx
CHANGED
|
@@ -143,47 +143,100 @@ function App() {
|
|
| 143 |
};
|
| 144 |
|
| 145 |
return (
|
| 146 |
-
<div className="flex flex-col h-screen w-full overflow-hidden">
|
| 147 |
-
|
| 148 |
-
|
|
|
|
| 149 |
<button
|
| 150 |
-
className="md:hidden bg-transparent border-0 text-
|
| 151 |
onClick={toggleMobileMenu}
|
| 152 |
>
|
| 153 |
-
|
|
|
|
|
|
|
| 154 |
</button>
|
| 155 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 156 |
</div>
|
| 157 |
-
|
|
|
|
|
|
|
|
|
|
| 158 |
<div className="relative">
|
| 159 |
<button
|
| 160 |
-
className="py-
|
| 161 |
onClick={toggleProfileDropdown}
|
| 162 |
>
|
| 163 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 164 |
</button>
|
|
|
|
| 165 |
{showProfileDropdown && (
|
| 166 |
-
<div className="absolute top-full right-0 w-
|
| 167 |
-
|
| 168 |
-
<div
|
| 169 |
-
|
| 170 |
-
className={`p-3 cursor-pointer transition-colors duration-200 text-sm ${profile.id === activeProfileId ? 'bg-active font-medium' : 'hover:bg-hover'}`}
|
| 171 |
-
onClick={() => handleProfileSelect(profile.id)}
|
| 172 |
-
>
|
| 173 |
-
{profile.name}
|
| 174 |
</div>
|
| 175 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 176 |
</div>
|
| 177 |
)}
|
| 178 |
</div>
|
|
|
|
|
|
|
| 179 |
<button
|
| 180 |
-
className="py-
|
| 181 |
onClick={toggleSettings}
|
| 182 |
>
|
| 183 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 184 |
</button>
|
| 185 |
</div>
|
| 186 |
-
</
|
| 187 |
|
| 188 |
<div className="flex flex-1 overflow-hidden">
|
| 189 |
<div className={`sidebar ${sidebarCollapsed ? 'collapsed' : ''} ${mobileMenuOpen ? 'mobile-open' : ''}`}>
|
|
|
|
| 143 |
};
|
| 144 |
|
| 145 |
return (
|
| 146 |
+
<div className="flex flex-col h-screen w-full overflow-hidden bg-background-secondary">
|
| 147 |
+
{/* Modern Enterprise Header */}
|
| 148 |
+
<header className="flex justify-between items-center px-6 h-header bg-background-elevated border-b border-border shadow-sm">
|
| 149 |
+
<div className="flex items-center gap-4">
|
| 150 |
<button
|
| 151 |
+
className="md:hidden bg-transparent border-0 text-lg text-muted cursor-pointer flex items-center justify-center z-10 w-10 h-10 rounded-lg hover:bg-background-secondary hover:text-primary transition-all duration-fast"
|
| 152 |
onClick={toggleMobileMenu}
|
| 153 |
>
|
| 154 |
+
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
| 155 |
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
|
| 156 |
+
</svg>
|
| 157 |
</button>
|
| 158 |
+
|
| 159 |
+
{/* Brand Section */}
|
| 160 |
+
<div className="flex items-center gap-3">
|
| 161 |
+
<div className="w-8 h-8 bg-gradient-to-br from-primary to-primary-dark rounded-lg flex items-center justify-center shadow-sm">
|
| 162 |
+
<svg className="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
| 163 |
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" />
|
| 164 |
+
</svg>
|
| 165 |
+
</div>
|
| 166 |
+
<div>
|
| 167 |
+
<h1 className="text-xl font-bold text-primary bg-gradient-to-r from-primary to-primary-dark bg-clip-text text-transparent">Thinking Model Client</h1>
|
| 168 |
+
<p className="text-xs text-muted hidden sm:block">Enterprise AI Assistant</p>
|
| 169 |
+
</div>
|
| 170 |
+
</div>
|
| 171 |
</div>
|
| 172 |
+
|
| 173 |
+
{/* Controls Section */}
|
| 174 |
+
<div className="flex items-center gap-3">
|
| 175 |
+
{/* Profile Selector */}
|
| 176 |
<div className="relative">
|
| 177 |
<button
|
| 178 |
+
className="flex items-center gap-2 py-2 px-4 bg-background-secondary border border-border rounded-lg text-sm text-secondary hover:bg-background-tertiary hover:text-primary hover:border-primary transition-all duration-fast shadow-sm"
|
| 179 |
onClick={toggleProfileDropdown}
|
| 180 |
>
|
| 181 |
+
<div className="w-6 h-6 bg-primary rounded-full flex items-center justify-center text-xs text-white font-medium">
|
| 182 |
+
{activeProfile.name.charAt(0).toUpperCase()}
|
| 183 |
+
</div>
|
| 184 |
+
<span className="hidden sm:inline font-medium">{activeProfile.name}</span>
|
| 185 |
+
<svg className={`w-4 h-4 transition-transform duration-fast ${showProfileDropdown ? 'rotate-180' : ''}`} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
| 186 |
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
| 187 |
+
</svg>
|
| 188 |
</button>
|
| 189 |
+
|
| 190 |
{showProfileDropdown && (
|
| 191 |
+
<div className="absolute top-full right-0 w-64 bg-background-elevated border border-border rounded-xl shadow-xl z-50 mt-2 animate-slide-up">
|
| 192 |
+
<div className="p-2">
|
| 193 |
+
<div className="px-3 py-2 text-xs font-semibold text-muted uppercase tracking-wider border-b border-border mb-2">
|
| 194 |
+
Select Profile
|
|
|
|
|
|
|
|
|
|
|
|
|
| 195 |
</div>
|
| 196 |
+
{profiles.map(profile => (
|
| 197 |
+
<button
|
| 198 |
+
key={profile.id}
|
| 199 |
+
className={`w-full flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all duration-fast text-sm text-left ${
|
| 200 |
+
profile.id === activeProfileId
|
| 201 |
+
? 'bg-primary-light text-primary font-medium shadow-sm'
|
| 202 |
+
: 'hover:bg-background-secondary text-secondary'
|
| 203 |
+
}`}
|
| 204 |
+
onClick={() => handleProfileSelect(profile.id)}
|
| 205 |
+
>
|
| 206 |
+
<div className={`w-8 h-8 rounded-full flex items-center justify-center text-xs font-medium ${
|
| 207 |
+
profile.id === activeProfileId ? 'bg-primary text-white' : 'bg-background-tertiary text-muted'
|
| 208 |
+
}`}>
|
| 209 |
+
{profile.name.charAt(0).toUpperCase()}
|
| 210 |
+
</div>
|
| 211 |
+
<div className="flex-1">
|
| 212 |
+
<div className="font-medium">{profile.name}</div>
|
| 213 |
+
<div className="text-xs text-muted truncate">{profile.model}</div>
|
| 214 |
+
</div>
|
| 215 |
+
{profile.id === activeProfileId && (
|
| 216 |
+
<svg className="w-4 h-4 text-primary" fill="currentColor" viewBox="0 0 20 20">
|
| 217 |
+
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
|
| 218 |
+
</svg>
|
| 219 |
+
)}
|
| 220 |
+
</button>
|
| 221 |
+
))}
|
| 222 |
+
</div>
|
| 223 |
</div>
|
| 224 |
)}
|
| 225 |
</div>
|
| 226 |
+
|
| 227 |
+
{/* Settings Button */}
|
| 228 |
<button
|
| 229 |
+
className="flex items-center gap-2 py-2 px-4 bg-background-secondary border border-border rounded-lg text-sm text-secondary hover:bg-background-tertiary hover:text-primary hover:border-primary transition-all duration-fast shadow-sm"
|
| 230 |
onClick={toggleSettings}
|
| 231 |
>
|
| 232 |
+
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
| 233 |
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
|
| 234 |
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
| 235 |
+
</svg>
|
| 236 |
+
<span className="hidden sm:inline font-medium">Settings</span>
|
| 237 |
</button>
|
| 238 |
</div>
|
| 239 |
+
</header>
|
| 240 |
|
| 241 |
<div className="flex flex-1 overflow-hidden">
|
| 242 |
<div className={`sidebar ${sidebarCollapsed ? 'collapsed' : ''} ${mobileMenuOpen ? 'mobile-open' : ''}`}>
|
src/components/ChatList.jsx
CHANGED
|
@@ -1,38 +1,146 @@
|
|
| 1 |
-
import React from 'react';
|
| 2 |
|
| 3 |
function ChatList({ chats, currentChat, onSelectChat, onDeleteChat, onCreateNewChat, collapsed, isStreamingChat }) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
return (
|
| 5 |
-
<div className="
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
</div>
|
| 24 |
-
<
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
</div>
|
| 34 |
-
)
|
| 35 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
</div>
|
| 37 |
);
|
| 38 |
}
|
|
|
|
| 1 |
+
import React, { useState } from 'react';
|
| 2 |
|
| 3 |
function ChatList({ chats, currentChat, onSelectChat, onDeleteChat, onCreateNewChat, collapsed, isStreamingChat }) {
|
| 4 |
+
const [hoveredChat, setHoveredChat] = useState(null);
|
| 5 |
+
|
| 6 |
+
const formatDate = (timestamp) => {
|
| 7 |
+
const date = new Date(timestamp);
|
| 8 |
+
const now = new Date();
|
| 9 |
+
const diffTime = Math.abs(now - date);
|
| 10 |
+
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
| 11 |
+
|
| 12 |
+
if (diffDays === 1) return 'Today';
|
| 13 |
+
if (diffDays === 2) return 'Yesterday';
|
| 14 |
+
if (diffDays <= 7) return `${diffDays} days ago`;
|
| 15 |
+
return date.toLocaleDateString();
|
| 16 |
+
};
|
| 17 |
+
|
| 18 |
+
const truncateTitle = (title, maxLength = 25) => {
|
| 19 |
+
if (title.length <= maxLength) return title;
|
| 20 |
+
return title.substring(0, maxLength) + '...';
|
| 21 |
+
};
|
| 22 |
+
|
| 23 |
return (
|
| 24 |
+
<div className="flex flex-col h-full bg-background-elevated">
|
| 25 |
+
{/* New Chat Button */}
|
| 26 |
+
<div className="p-3 border-b border-border">
|
| 27 |
+
<button
|
| 28 |
+
className="w-full flex items-center justify-center gap-2 py-3 px-4 bg-primary hover:bg-primary-hover text-white border-none rounded-xl cursor-pointer text-sm font-medium transition-all duration-fast shadow-sm hover:shadow-md active:scale-[0.98]"
|
| 29 |
+
onClick={onCreateNewChat}
|
| 30 |
+
>
|
| 31 |
+
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
| 32 |
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" />
|
| 33 |
+
</svg>
|
| 34 |
+
<span>New Conversation</span>
|
| 35 |
+
</button>
|
| 36 |
+
</div>
|
| 37 |
+
|
| 38 |
+
{/* Chat List */}
|
| 39 |
+
<div className="flex-1 overflow-y-auto p-2">
|
| 40 |
+
{chats.length === 0 ? (
|
| 41 |
+
<div className="flex flex-col items-center justify-center py-12 px-4 text-center">
|
| 42 |
+
<div className="w-16 h-16 bg-background-secondary rounded-full flex items-center justify-center mb-4">
|
| 43 |
+
<svg className="w-8 h-8 text-muted" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
| 44 |
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
|
| 45 |
+
</svg>
|
| 46 |
</div>
|
| 47 |
+
<h3 className="text-sm font-medium text-secondary mb-2">No conversations yet</h3>
|
| 48 |
+
<p className="text-xs text-muted">Start a new conversation to get started</p>
|
| 49 |
+
</div>
|
| 50 |
+
) : (
|
| 51 |
+
<div className="space-y-1">
|
| 52 |
+
{chats.map(chat => {
|
| 53 |
+
const isActive = chat.id === currentChat?.id;
|
| 54 |
+
const isStreaming = isStreamingChat && typeof isStreamingChat === 'function' && isStreamingChat(chat.id);
|
| 55 |
+
const isHovered = hoveredChat === chat.id;
|
| 56 |
+
|
| 57 |
+
return (
|
| 58 |
+
<div
|
| 59 |
+
key={chat.id}
|
| 60 |
+
className={`group relative flex items-center p-3 rounded-lg cursor-pointer transition-all duration-fast ${
|
| 61 |
+
isActive
|
| 62 |
+
? 'bg-primary-light border border-primary/20 shadow-sm'
|
| 63 |
+
: 'hover:bg-background-secondary border border-transparent'
|
| 64 |
+
}`}
|
| 65 |
+
onClick={() => onSelectChat(chat.id)}
|
| 66 |
+
onMouseEnter={() => setHoveredChat(chat.id)}
|
| 67 |
+
onMouseLeave={() => setHoveredChat(null)}
|
| 68 |
+
>
|
| 69 |
+
{/* Streaming indicator */}
|
| 70 |
+
{isStreaming && (
|
| 71 |
+
<div className="absolute left-0 top-0 bottom-0 w-1 bg-gradient-to-b from-info to-primary rounded-r-full animate-pulse" />
|
| 72 |
+
)}
|
| 73 |
+
|
| 74 |
+
<div className="flex-1 min-w-0">
|
| 75 |
+
<div className="flex items-center gap-2 mb-1">
|
| 76 |
+
{/* Chat icon */}
|
| 77 |
+
<div className={`flex-shrink-0 w-8 h-8 rounded-lg flex items-center justify-center ${
|
| 78 |
+
isActive ? 'bg-primary text-white' : 'bg-background-tertiary text-muted'
|
| 79 |
+
}`}>
|
| 80 |
+
{isStreaming ? (
|
| 81 |
+
<div className="w-2 h-2 bg-current rounded-full animate-pulse" />
|
| 82 |
+
) : (
|
| 83 |
+
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
| 84 |
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
|
| 85 |
+
</svg>
|
| 86 |
+
)}
|
| 87 |
+
</div>
|
| 88 |
+
|
| 89 |
+
{/* Chat title */}
|
| 90 |
+
<div className="flex-1 min-w-0">
|
| 91 |
+
<h4 className={`text-sm font-medium truncate ${
|
| 92 |
+
isActive ? 'text-primary' : 'text-secondary'
|
| 93 |
+
}`}>
|
| 94 |
+
{truncateTitle(chat.title)}
|
| 95 |
+
</h4>
|
| 96 |
+
|
| 97 |
+
{/* Message count and date */}
|
| 98 |
+
<div className="flex items-center justify-between mt-1">
|
| 99 |
+
<span className="text-xs text-muted">
|
| 100 |
+
{chat.messages?.length || 0} messages
|
| 101 |
+
</span>
|
| 102 |
+
{chat.messages?.length > 0 && (
|
| 103 |
+
<span className="text-xs text-muted">
|
| 104 |
+
{formatDate(chat.messages[chat.messages.length - 1]?.timestamp || Date.now())}
|
| 105 |
+
</span>
|
| 106 |
+
)}
|
| 107 |
+
</div>
|
| 108 |
+
</div>
|
| 109 |
+
</div>
|
| 110 |
+
</div>
|
| 111 |
+
|
| 112 |
+
{/* Delete button */}
|
| 113 |
+
<button
|
| 114 |
+
className={`flex-shrink-0 ml-2 p-1.5 rounded-md transition-all duration-fast ${
|
| 115 |
+
isHovered || isActive
|
| 116 |
+
? 'opacity-100 hover:bg-error-light hover:text-error'
|
| 117 |
+
: 'opacity-0 group-hover:opacity-100'
|
| 118 |
+
}`}
|
| 119 |
+
onClick={(e) => {
|
| 120 |
+
e.stopPropagation();
|
| 121 |
+
if (window.confirm('Are you sure you want to delete this conversation?')) {
|
| 122 |
+
onDeleteChat(chat.id);
|
| 123 |
+
}
|
| 124 |
+
}}
|
| 125 |
+
title="Delete conversation"
|
| 126 |
+
>
|
| 127 |
+
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
| 128 |
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
|
| 129 |
+
</svg>
|
| 130 |
+
</button>
|
| 131 |
+
</div>
|
| 132 |
+
);
|
| 133 |
+
})}
|
| 134 |
</div>
|
| 135 |
+
)}
|
| 136 |
+
</div>
|
| 137 |
+
|
| 138 |
+
{/* Footer */}
|
| 139 |
+
<div className="p-3 border-t border-border">
|
| 140 |
+
<div className="text-xs text-muted text-center">
|
| 141 |
+
{chats.length} conversation{chats.length !== 1 ? 's' : ''}
|
| 142 |
+
</div>
|
| 143 |
+
</div>
|
| 144 |
</div>
|
| 145 |
);
|
| 146 |
}
|
src/components/ChatWindow.jsx
CHANGED
|
@@ -997,25 +997,7 @@ function ChatWindow({
|
|
| 997 |
const mcpTools = getAllTools();
|
| 998 |
|
| 999 |
return (
|
| 1000 |
-
<div className="
|
| 1001 |
-
{/* Floating New Chat button */}
|
| 1002 |
-
<button
|
| 1003 |
-
onClick={() => {
|
| 1004 |
-
console.log('Floating new chat button clicked');
|
| 1005 |
-
// ε¨εε»Ίζ°θ倩εζ·»ε δΈδΊζ₯εΏ
|
| 1006 |
-
if (typeof onCreateNewChat === 'function') {
|
| 1007 |
-
console.log('Calling onCreateNewChat function');
|
| 1008 |
-
onCreateNewChat();
|
| 1009 |
-
console.log('onCreateNewChat function called');
|
| 1010 |
-
} else {
|
| 1011 |
-
console.error('onCreateNewChat is not a function');
|
| 1012 |
-
}
|
| 1013 |
-
}}
|
| 1014 |
-
className="floating-new-chat"
|
| 1015 |
-
title="Create a new conversation"
|
| 1016 |
-
>
|
| 1017 |
-
<span className="text-xl">+</span>
|
| 1018 |
-
</button>
|
| 1019 |
<div className="chat-messages">
|
| 1020 |
{chat && chat.messages && chat.messages.map((message, index) => {
|
| 1021 |
const parsedMessage = message.role === 'assistant'
|
|
|
|
| 997 |
const mcpTools = getAllTools();
|
| 998 |
|
| 999 |
return (
|
| 1000 |
+
<div className="flex flex-col h-full bg-background-primary">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1001 |
<div className="chat-messages">
|
| 1002 |
{chat && chat.messages && chat.messages.map((message, index) => {
|
| 1003 |
const parsedMessage = message.role === 'assistant'
|
src/index.css
CHANGED
|
@@ -6,28 +6,78 @@
|
|
| 6 |
@tailwind components;
|
| 7 |
@tailwind utilities;
|
| 8 |
|
| 9 |
-
/*
|
| 10 |
:root {
|
| 11 |
-
|
| 12 |
-
--primary-
|
| 13 |
-
--
|
| 14 |
-
--light
|
| 15 |
-
--
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
--
|
| 19 |
-
--
|
| 20 |
-
--
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
--
|
| 24 |
-
--
|
| 25 |
-
--
|
| 26 |
-
--
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
|
| 28 |
/* Responsive sidebar width */
|
| 29 |
--mobile-sidebar-width: 100%;
|
| 30 |
-
--tablet-sidebar-width:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
}
|
| 32 |
|
| 33 |
* {
|
|
|
|
| 6 |
@tailwind components;
|
| 7 |
@tailwind utilities;
|
| 8 |
|
| 9 |
+
/* Enterprise Design System */
|
| 10 |
:root {
|
| 11 |
+
/* Primary Brand Colors */
|
| 12 |
+
--primary-color: #2563eb;
|
| 13 |
+
--primary-hover: #1d4ed8;
|
| 14 |
+
--primary-light: #dbeafe;
|
| 15 |
+
--primary-dark: #1e3a8a;
|
| 16 |
+
|
| 17 |
+
/* Secondary Colors */
|
| 18 |
+
--secondary-color: #64748b;
|
| 19 |
+
--secondary-hover: #475569;
|
| 20 |
+
--secondary-light: #f1f5f9;
|
| 21 |
+
|
| 22 |
+
/* Neutral Palette */
|
| 23 |
+
--text-color: #0f172a;
|
| 24 |
+
--text-secondary: #334155;
|
| 25 |
+
--text-muted: #64748b;
|
| 26 |
+
--text-light: #94a3b8;
|
| 27 |
+
--text-disabled: #cbd5e1;
|
| 28 |
+
|
| 29 |
+
/* Background System */
|
| 30 |
+
--background-primary: #ffffff;
|
| 31 |
+
--background-secondary: #f8fafc;
|
| 32 |
+
--background-tertiary: #f1f5f9;
|
| 33 |
+
--background-elevated: #ffffff;
|
| 34 |
+
|
| 35 |
+
/* Border System */
|
| 36 |
+
--border-color: #e2e8f0;
|
| 37 |
+
--border-light: #f1f5f9;
|
| 38 |
+
--border-dark: #cbd5e1;
|
| 39 |
+
--border-accent: #3b82f6;
|
| 40 |
+
|
| 41 |
+
/* Status Colors */
|
| 42 |
+
--success-color: #059669;
|
| 43 |
+
--success-light: #d1fae5;
|
| 44 |
+
--warning-color: #d97706;
|
| 45 |
+
--warning-light: #fef3c7;
|
| 46 |
+
--error-color: #dc2626;
|
| 47 |
+
--error-light: #fee2e2;
|
| 48 |
+
--info-color: #0284c7;
|
| 49 |
+
--info-light: #e0f2fe;
|
| 50 |
+
|
| 51 |
+
/* Layout Variables */
|
| 52 |
+
--sidebar-width: 320px;
|
| 53 |
+
--header-height: 64px;
|
| 54 |
+
--border-radius: 8px;
|
| 55 |
+
--border-radius-lg: 12px;
|
| 56 |
+
--border-radius-xl: 16px;
|
| 57 |
+
|
| 58 |
+
/* Shadow System */
|
| 59 |
+
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
| 60 |
+
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
| 61 |
+
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
| 62 |
+
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
|
| 63 |
+
|
| 64 |
+
/* Message Specific */
|
| 65 |
+
--reasoning-background: var(--background-tertiary);
|
| 66 |
+
--user-message-bg: var(--primary-color);
|
| 67 |
+
--user-message-color: #ffffff;
|
| 68 |
+
--assistant-message-bg: var(--background-elevated);
|
| 69 |
+
--assistant-message-color: var(--text-color);
|
| 70 |
+
--hover-color: var(--background-secondary);
|
| 71 |
+
--active-color: var(--primary-light);
|
| 72 |
|
| 73 |
/* Responsive sidebar width */
|
| 74 |
--mobile-sidebar-width: 100%;
|
| 75 |
+
--tablet-sidebar-width: 280px;
|
| 76 |
+
|
| 77 |
+
/* Animation System */
|
| 78 |
+
--transition-fast: 150ms ease-out;
|
| 79 |
+
--transition-normal: 250ms ease-out;
|
| 80 |
+
--transition-slow: 350ms ease-out;
|
| 81 |
}
|
| 82 |
|
| 83 |
* {
|
tailwind.config.js
CHANGED
|
@@ -7,13 +7,62 @@ export default {
|
|
| 7 |
theme: {
|
| 8 |
extend: {
|
| 9 |
colors: {
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
'primary-hover': 'var(--primary-hover)',
|
| 12 |
-
'text': 'var(--text-
|
| 13 |
-
'
|
| 14 |
-
'lightest-text': 'var(--lightest-text)',
|
| 15 |
-
'border': 'var(--border-color)',
|
| 16 |
-
'background': 'var(--background-color)',
|
| 17 |
'reasoning-bg': 'var(--reasoning-background)',
|
| 18 |
'user-message-bg': 'var(--user-message-bg)',
|
| 19 |
'user-message-color': 'var(--user-message-color)',
|
|
@@ -26,14 +75,58 @@ export default {
|
|
| 26 |
'sidebar': 'var(--sidebar-width)',
|
| 27 |
'header': 'var(--header-height)',
|
| 28 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
animation: {
|
| 30 |
'blink': 'blink 1s infinite',
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
},
|
| 32 |
keyframes: {
|
| 33 |
blink: {
|
| 34 |
'0%, 100%': { opacity: 1 },
|
| 35 |
'50%': { opacity: 0 },
|
| 36 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
},
|
| 38 |
},
|
| 39 |
},
|
|
|
|
| 7 |
theme: {
|
| 8 |
extend: {
|
| 9 |
colors: {
|
| 10 |
+
// Primary brand colors
|
| 11 |
+
primary: {
|
| 12 |
+
DEFAULT: 'var(--primary-color)',
|
| 13 |
+
hover: 'var(--primary-hover)',
|
| 14 |
+
light: 'var(--primary-light)',
|
| 15 |
+
dark: 'var(--primary-dark)',
|
| 16 |
+
},
|
| 17 |
+
// Secondary colors
|
| 18 |
+
secondary: {
|
| 19 |
+
DEFAULT: 'var(--secondary-color)',
|
| 20 |
+
hover: 'var(--secondary-hover)',
|
| 21 |
+
light: 'var(--secondary-light)',
|
| 22 |
+
},
|
| 23 |
+
// Text colors
|
| 24 |
+
text: {
|
| 25 |
+
DEFAULT: 'var(--text-color)',
|
| 26 |
+
secondary: 'var(--text-secondary)',
|
| 27 |
+
muted: 'var(--text-muted)',
|
| 28 |
+
light: 'var(--text-light)',
|
| 29 |
+
disabled: 'var(--text-disabled)',
|
| 30 |
+
},
|
| 31 |
+
// Background colors
|
| 32 |
+
background: {
|
| 33 |
+
DEFAULT: 'var(--background-primary)',
|
| 34 |
+
secondary: 'var(--background-secondary)',
|
| 35 |
+
tertiary: 'var(--background-tertiary)',
|
| 36 |
+
elevated: 'var(--background-elevated)',
|
| 37 |
+
},
|
| 38 |
+
// Border colors
|
| 39 |
+
border: {
|
| 40 |
+
DEFAULT: 'var(--border-color)',
|
| 41 |
+
light: 'var(--border-light)',
|
| 42 |
+
dark: 'var(--border-dark)',
|
| 43 |
+
accent: 'var(--border-accent)',
|
| 44 |
+
},
|
| 45 |
+
// Status colors
|
| 46 |
+
success: {
|
| 47 |
+
DEFAULT: 'var(--success-color)',
|
| 48 |
+
light: 'var(--success-light)',
|
| 49 |
+
},
|
| 50 |
+
warning: {
|
| 51 |
+
DEFAULT: 'var(--warning-color)',
|
| 52 |
+
light: 'var(--warning-light)',
|
| 53 |
+
},
|
| 54 |
+
error: {
|
| 55 |
+
DEFAULT: 'var(--error-color)',
|
| 56 |
+
light: 'var(--error-light)',
|
| 57 |
+
},
|
| 58 |
+
info: {
|
| 59 |
+
DEFAULT: 'var(--info-color)',
|
| 60 |
+
light: 'var(--info-light)',
|
| 61 |
+
},
|
| 62 |
+
// Legacy color mappings (for backwards compatibility)
|
| 63 |
'primary-hover': 'var(--primary-hover)',
|
| 64 |
+
'light-text': 'var(--text-light)',
|
| 65 |
+
'lightest-text': 'var(--text-disabled)',
|
|
|
|
|
|
|
|
|
|
| 66 |
'reasoning-bg': 'var(--reasoning-background)',
|
| 67 |
'user-message-bg': 'var(--user-message-bg)',
|
| 68 |
'user-message-color': 'var(--user-message-color)',
|
|
|
|
| 75 |
'sidebar': 'var(--sidebar-width)',
|
| 76 |
'header': 'var(--header-height)',
|
| 77 |
},
|
| 78 |
+
borderRadius: {
|
| 79 |
+
'DEFAULT': 'var(--border-radius)',
|
| 80 |
+
'lg': 'var(--border-radius-lg)',
|
| 81 |
+
'xl': 'var(--border-radius-xl)',
|
| 82 |
+
},
|
| 83 |
+
boxShadow: {
|
| 84 |
+
'sm': 'var(--shadow-sm)',
|
| 85 |
+
'DEFAULT': 'var(--shadow-md)',
|
| 86 |
+
'md': 'var(--shadow-md)',
|
| 87 |
+
'lg': 'var(--shadow-lg)',
|
| 88 |
+
'xl': 'var(--shadow-xl)',
|
| 89 |
+
},
|
| 90 |
+
transitionDuration: {
|
| 91 |
+
'fast': 'var(--transition-fast)',
|
| 92 |
+
'normal': 'var(--transition-normal)',
|
| 93 |
+
'slow': 'var(--transition-slow)',
|
| 94 |
+
},
|
| 95 |
animation: {
|
| 96 |
'blink': 'blink 1s infinite',
|
| 97 |
+
'pulse-slow': 'pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
| 98 |
+
'fade-in': 'fadeIn 0.5s ease-out',
|
| 99 |
+
'slide-up': 'slideUp 0.3s ease-out',
|
| 100 |
+
'scale-in': 'scaleIn 0.2s ease-out',
|
| 101 |
},
|
| 102 |
keyframes: {
|
| 103 |
blink: {
|
| 104 |
'0%, 100%': { opacity: 1 },
|
| 105 |
'50%': { opacity: 0 },
|
| 106 |
},
|
| 107 |
+
fadeIn: {
|
| 108 |
+
'0%': { opacity: 0 },
|
| 109 |
+
'100%': { opacity: 1 },
|
| 110 |
+
},
|
| 111 |
+
slideUp: {
|
| 112 |
+
'0%': { transform: 'translateY(10px)', opacity: 0 },
|
| 113 |
+
'100%': { transform: 'translateY(0)', opacity: 1 },
|
| 114 |
+
},
|
| 115 |
+
scaleIn: {
|
| 116 |
+
'0%': { transform: 'scale(0.95)', opacity: 0 },
|
| 117 |
+
'100%': { transform: 'scale(1)', opacity: 1 },
|
| 118 |
+
},
|
| 119 |
+
},
|
| 120 |
+
fontFamily: {
|
| 121 |
+
'sans': ['-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'Helvetica Neue', 'Arial', 'sans-serif'],
|
| 122 |
+
},
|
| 123 |
+
fontSize: {
|
| 124 |
+
'xs': ['0.75rem', { lineHeight: '1rem' }],
|
| 125 |
+
'sm': ['0.875rem', { lineHeight: '1.25rem' }],
|
| 126 |
+
'base': ['1rem', { lineHeight: '1.5rem' }],
|
| 127 |
+
'lg': ['1.125rem', { lineHeight: '1.75rem' }],
|
| 128 |
+
'xl': ['1.25rem', { lineHeight: '1.75rem' }],
|
| 129 |
+
'2xl': ['1.5rem', { lineHeight: '2rem' }],
|
| 130 |
},
|
| 131 |
},
|
| 132 |
},
|
test-xsai.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env node
|
| 2 |
+
|
| 3 |
+
import { streamText } from '@xsai/stream-text';
|
| 4 |
+
import { generateText } from '@xsai/generate-text';
|
| 5 |
+
import { extractReasoningStream } from '@xsai/utils-reasoning';
|
| 6 |
+
|
| 7 |
+
// Test configuration - replace with your actual API details
|
| 8 |
+
const testConfig = {
|
| 9 |
+
baseURL: 'https://api.deepseek.com/v1', // Example - replace with your API endpoint
|
| 10 |
+
apiKey: 'your-api-key-here', // Replace with your actual API key
|
| 11 |
+
model: 'deepseek-r1' // Replace with your model
|
| 12 |
+
};
|
| 13 |
+
|
| 14 |
+
async function testGenerateText() {
|
| 15 |
+
console.log('π§ͺ Testing xsai generateText integration...\n');
|
| 16 |
+
|
| 17 |
+
try {
|
| 18 |
+
const { text } = await generateText({
|
| 19 |
+
apiKey: testConfig.apiKey,
|
| 20 |
+
baseURL: testConfig.baseURL,
|
| 21 |
+
model: testConfig.model,
|
| 22 |
+
messages: [{
|
| 23 |
+
role: 'user',
|
| 24 |
+
content: 'Summarize this in 3-5 words: Hello, how are you today? I am doing well, thanks for asking!'
|
| 25 |
+
}],
|
| 26 |
+
temperature: 0.2,
|
| 27 |
+
max_tokens: 20
|
| 28 |
+
});
|
| 29 |
+
|
| 30 |
+
console.log('β
GenerateText test successful!');
|
| 31 |
+
console.log('π Summary result:', text.trim());
|
| 32 |
+
|
| 33 |
+
} catch (error) {
|
| 34 |
+
console.error('β GenerateText test failed:', error.message);
|
| 35 |
+
}
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
async function testStreamText() {
|
| 39 |
+
console.log('\nπ§ͺ Testing xsai streamText with reasoning extraction...\n');
|
| 40 |
+
|
| 41 |
+
try {
|
| 42 |
+
const { textStream } = await streamText({
|
| 43 |
+
apiKey: testConfig.apiKey,
|
| 44 |
+
baseURL: testConfig.baseURL,
|
| 45 |
+
model: testConfig.model,
|
| 46 |
+
messages: [
|
| 47 |
+
{ role: 'system', content: 'You are a helpful assistant. Use <think></think> tags to show your reasoning process.' },
|
| 48 |
+
{ role: 'user', content: 'Why is the sky blue? Please think through this step by step.' }
|
| 49 |
+
]
|
| 50 |
+
});
|
| 51 |
+
|
| 52 |
+
// Extract reasoning and content streams
|
| 53 |
+
const { reasoningStream, textStream: contentStream } = extractReasoningStream(textStream);
|
| 54 |
+
|
| 55 |
+
console.log('π§ Reasoning process:');
|
| 56 |
+
console.log('='.repeat(50));
|
| 57 |
+
let reasoningText = '';
|
| 58 |
+
for await (const chunk of reasoningStream) {
|
| 59 |
+
process.stdout.write(chunk);
|
| 60 |
+
reasoningText += chunk;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
console.log('\n' + '='.repeat(50));
|
| 64 |
+
console.log('\n㪠Final answer:');
|
| 65 |
+
console.log('='.repeat(50));
|
| 66 |
+
for await (const chunk of contentStream) {
|
| 67 |
+
process.stdout.write(chunk);
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
console.log('\n' + '='.repeat(50));
|
| 71 |
+
console.log('\nβ
StreamText test successful!');
|
| 72 |
+
|
| 73 |
+
} catch (error) {
|
| 74 |
+
console.error('β StreamText test failed:', error.message);
|
| 75 |
+
}
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
async function runTests() {
|
| 79 |
+
console.log('π Testing xsai integration for thinking-model-client\n');
|
| 80 |
+
|
| 81 |
+
// Check if configuration is set
|
| 82 |
+
if (testConfig.apiKey === 'your-api-key-here') {
|
| 83 |
+
console.log('β οΈ Please update the testConfig in this file with your actual API details before running tests.');
|
| 84 |
+
console.log('π Edit the testConfig object at the top of this file.');
|
| 85 |
+
return;
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
await testGenerateText();
|
| 89 |
+
await testStreamText();
|
| 90 |
+
|
| 91 |
+
console.log('\nπ All tests completed!');
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
runTests().catch(console.error);
|