Spaces:
Runtime error
Runtime error
refactor: completely remove PWA functionality
Browse files- Delete all PWA-related files:
- public/sw.js (service worker)
- public/manifest.json (PWA manifest)
- public/icons/ directory (PWA icons)
- src/serviceWorkerRegistration.js
- src/utils/clearCache.js
- scripts/generate-icons.js
- XSAI_INTEGRATION_SUMMARY.md
- test-xsai.js
- Clean up HTML references:
- Remove manifest.json link
- Remove apple-touch-icon link
- Remove theme-color meta tag
- Remove from main.jsx:
- Remove service worker import and registration
- Remove from Settings.jsx:
- Remove clearCache utility imports
- Remove developer tools section entirely
- Clean up CSS:
- Remove all developer tools related styles
This completely removes PWA functionality from the project as requested.
- XSAI_INTEGRATION_SUMMARY.md +0 -120
- index.html +0 -3
- public/icons/icon-192x192.png +0 -1
- public/icons/icon-512x512.png +0 -1
- public/icons/icon-512x512.svg +0 -6
- public/manifest.json +0 -59
- public/sw.js +0 -80
- scripts/generate-icons.js +0 -41
- src/components/Settings.jsx +0 -91
- src/index.css +0 -107
- src/main.jsx +0 -4
- src/serviceWorkerRegistration.js +0 -134
- src/utils/clearCache.js +0 -68
- test-xsai.js +0 -94
XSAI_INTEGRATION_SUMMARY.md
DELETED
|
@@ -1,120 +0,0 @@
|
|
| 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!
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
index.html
CHANGED
|
@@ -5,9 +5,6 @@
|
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
| 6 |
<title>Thinking Model Client</title>
|
| 7 |
<meta name="description" content="A client for interacting with thinking models" />
|
| 8 |
-
<meta name="theme-color" content="#3e6ae1" />
|
| 9 |
-
<link rel="manifest" href="/manifest.json" />
|
| 10 |
-
<link rel="apple-touch-icon" href="/icons/icon-192x192.png" />
|
| 11 |
<link rel="preconnect" href="https://fonts.googleapis.com">
|
| 12 |
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
| 13 |
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
|
|
|
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
| 6 |
<title>Thinking Model Client</title>
|
| 7 |
<meta name="description" content="A client for interacting with thinking models" />
|
|
|
|
|
|
|
|
|
|
| 8 |
<link rel="preconnect" href="https://fonts.googleapis.com">
|
| 9 |
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
| 10 |
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
|
public/icons/icon-192x192.png
DELETED
public/icons/icon-512x512.png
DELETED
public/icons/icon-512x512.svg
DELETED
public/manifest.json
DELETED
|
@@ -1,59 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"name": "Thinking Model Client",
|
| 3 |
-
"short_name": "Thinking Model",
|
| 4 |
-
"description": "A client for interacting with thinking models",
|
| 5 |
-
"start_url": "/",
|
| 6 |
-
"display": "standalone",
|
| 7 |
-
"background_color": "#ffffff",
|
| 8 |
-
"theme_color": "#3e6ae1",
|
| 9 |
-
"icons": [
|
| 10 |
-
{
|
| 11 |
-
"src": "icons/icon-72x72.png",
|
| 12 |
-
"sizes": "72x72",
|
| 13 |
-
"type": "image/png",
|
| 14 |
-
"purpose": "any maskable"
|
| 15 |
-
},
|
| 16 |
-
{
|
| 17 |
-
"src": "icons/icon-96x96.png",
|
| 18 |
-
"sizes": "96x96",
|
| 19 |
-
"type": "image/png",
|
| 20 |
-
"purpose": "any maskable"
|
| 21 |
-
},
|
| 22 |
-
{
|
| 23 |
-
"src": "icons/icon-128x128.png",
|
| 24 |
-
"sizes": "128x128",
|
| 25 |
-
"type": "image/png",
|
| 26 |
-
"purpose": "any maskable"
|
| 27 |
-
},
|
| 28 |
-
{
|
| 29 |
-
"src": "icons/icon-144x144.png",
|
| 30 |
-
"sizes": "144x144",
|
| 31 |
-
"type": "image/png",
|
| 32 |
-
"purpose": "any maskable"
|
| 33 |
-
},
|
| 34 |
-
{
|
| 35 |
-
"src": "icons/icon-152x152.png",
|
| 36 |
-
"sizes": "152x152",
|
| 37 |
-
"type": "image/png",
|
| 38 |
-
"purpose": "any maskable"
|
| 39 |
-
},
|
| 40 |
-
{
|
| 41 |
-
"src": "icons/icon-192x192.png",
|
| 42 |
-
"sizes": "192x192",
|
| 43 |
-
"type": "image/png",
|
| 44 |
-
"purpose": "any maskable"
|
| 45 |
-
},
|
| 46 |
-
{
|
| 47 |
-
"src": "icons/icon-384x384.png",
|
| 48 |
-
"sizes": "384x384",
|
| 49 |
-
"type": "image/png",
|
| 50 |
-
"purpose": "any maskable"
|
| 51 |
-
},
|
| 52 |
-
{
|
| 53 |
-
"src": "icons/icon-512x512.png",
|
| 54 |
-
"sizes": "512x512",
|
| 55 |
-
"type": "image/png",
|
| 56 |
-
"purpose": "any maskable"
|
| 57 |
-
}
|
| 58 |
-
]
|
| 59 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public/sw.js
DELETED
|
@@ -1,80 +0,0 @@
|
|
| 1 |
-
// Service Worker for Thinking Model Client PWA
|
| 2 |
-
|
| 3 |
-
const CACHE_NAME = 'thinking-model-cache-v1';
|
| 4 |
-
const urlsToCache = [
|
| 5 |
-
'/',
|
| 6 |
-
'/index.html',
|
| 7 |
-
'/manifest.json',
|
| 8 |
-
'/icons/icon-192x192.png',
|
| 9 |
-
'/icons/icon-512x512.png'
|
| 10 |
-
];
|
| 11 |
-
|
| 12 |
-
// Install event - cache basic assets
|
| 13 |
-
self.addEventListener('install', event => {
|
| 14 |
-
event.waitUntil(
|
| 15 |
-
caches.open(CACHE_NAME)
|
| 16 |
-
.then(cache => {
|
| 17 |
-
console.log('Opened cache');
|
| 18 |
-
return cache.addAll(urlsToCache);
|
| 19 |
-
})
|
| 20 |
-
);
|
| 21 |
-
});
|
| 22 |
-
|
| 23 |
-
// Activate event - clean up old caches
|
| 24 |
-
self.addEventListener('activate', event => {
|
| 25 |
-
const cacheWhitelist = [CACHE_NAME];
|
| 26 |
-
event.waitUntil(
|
| 27 |
-
caches.keys().then(cacheNames => {
|
| 28 |
-
return Promise.all(
|
| 29 |
-
cacheNames.map(cacheName => {
|
| 30 |
-
if (cacheWhitelist.indexOf(cacheName) === -1) {
|
| 31 |
-
return caches.delete(cacheName);
|
| 32 |
-
}
|
| 33 |
-
})
|
| 34 |
-
);
|
| 35 |
-
})
|
| 36 |
-
);
|
| 37 |
-
});
|
| 38 |
-
|
| 39 |
-
// Fetch event - serve from cache if available, otherwise fetch from network
|
| 40 |
-
self.addEventListener('fetch', event => {
|
| 41 |
-
// Skip caching for localhost/development
|
| 42 |
-
const isLocalhost = event.request.url.includes('localhost') || event.request.url.includes('127.0.0.1');
|
| 43 |
-
|
| 44 |
-
if (isLocalhost) {
|
| 45 |
-
// In development, always fetch from network (no caching)
|
| 46 |
-
event.respondWith(fetch(event.request));
|
| 47 |
-
return;
|
| 48 |
-
}
|
| 49 |
-
|
| 50 |
-
event.respondWith(
|
| 51 |
-
caches.match(event.request)
|
| 52 |
-
.then(response => {
|
| 53 |
-
// Cache hit - return response
|
| 54 |
-
if (response) {
|
| 55 |
-
return response;
|
| 56 |
-
}
|
| 57 |
-
return fetch(event.request).then(
|
| 58 |
-
response => {
|
| 59 |
-
// Check if we received a valid response
|
| 60 |
-
if (!response || response.status !== 200 || response.type !== 'basic') {
|
| 61 |
-
return response;
|
| 62 |
-
}
|
| 63 |
-
|
| 64 |
-
// Clone the response
|
| 65 |
-
const responseToCache = response.clone();
|
| 66 |
-
|
| 67 |
-
caches.open(CACHE_NAME)
|
| 68 |
-
.then(cache => {
|
| 69 |
-
// Don't cache API requests
|
| 70 |
-
if (!event.request.url.includes('/api/')) {
|
| 71 |
-
cache.put(event.request, responseToCache);
|
| 72 |
-
}
|
| 73 |
-
});
|
| 74 |
-
|
| 75 |
-
return response;
|
| 76 |
-
}
|
| 77 |
-
);
|
| 78 |
-
})
|
| 79 |
-
);
|
| 80 |
-
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
scripts/generate-icons.js
DELETED
|
@@ -1,41 +0,0 @@
|
|
| 1 |
-
// This script can be used to generate different sized icons from the SVG source
|
| 2 |
-
// You would need to install sharp: npm install sharp
|
| 3 |
-
// Then run: node scripts/generate-icons.js
|
| 4 |
-
|
| 5 |
-
const fs = require('fs');
|
| 6 |
-
const path = require('path');
|
| 7 |
-
const sharp = require('sharp');
|
| 8 |
-
|
| 9 |
-
const sizes = [72, 96, 128, 144, 152, 192, 384, 512];
|
| 10 |
-
const svgPath = path.join(__dirname, '../public/icons/icon-512x512.svg');
|
| 11 |
-
const outputDir = path.join(__dirname, '../public/icons');
|
| 12 |
-
|
| 13 |
-
async function generateIcons() {
|
| 14 |
-
try {
|
| 15 |
-
// Make sure the output directory exists
|
| 16 |
-
if (!fs.existsSync(outputDir)) {
|
| 17 |
-
fs.mkdirSync(outputDir, { recursive: true });
|
| 18 |
-
}
|
| 19 |
-
|
| 20 |
-
// Read the SVG file
|
| 21 |
-
const svgBuffer = fs.readFileSync(svgPath);
|
| 22 |
-
|
| 23 |
-
// Generate each size
|
| 24 |
-
for (const size of sizes) {
|
| 25 |
-
const outputPath = path.join(outputDir, `icon-${size}x${size}.png`);
|
| 26 |
-
|
| 27 |
-
await sharp(svgBuffer)
|
| 28 |
-
.resize(size, size)
|
| 29 |
-
.png()
|
| 30 |
-
.toFile(outputPath);
|
| 31 |
-
|
| 32 |
-
console.log(`Generated: ${outputPath}`);
|
| 33 |
-
}
|
| 34 |
-
|
| 35 |
-
console.log('All icons generated successfully!');
|
| 36 |
-
} catch (error) {
|
| 37 |
-
console.error('Error generating icons:', error);
|
| 38 |
-
}
|
| 39 |
-
}
|
| 40 |
-
|
| 41 |
-
generateIcons();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/components/Settings.jsx
CHANGED
|
@@ -1,5 +1,4 @@
|
|
| 1 |
import { useState, useEffect } from 'react';
|
| 2 |
-
import { clearAllCache, hardRefresh, checkCacheStatus } from '../utils/clearCache';
|
| 3 |
|
| 4 |
function Settings({
|
| 5 |
profiles,
|
|
@@ -707,96 +706,6 @@ function Settings({
|
|
| 707 |
)}
|
| 708 |
</div>
|
| 709 |
|
| 710 |
-
{/* Developer Tools Section */}
|
| 711 |
-
<div className="profiles-section">
|
| 712 |
-
<h3>Developer Tools</h3>
|
| 713 |
-
<div className="developer-tools-section">
|
| 714 |
-
<div className="tool-group">
|
| 715 |
-
<h4>Cache Management</h4>
|
| 716 |
-
<p className="tool-description">Clear PWA cache and service workers that might interfere with page refreshing.</p>
|
| 717 |
-
|
| 718 |
-
<div className="tool-buttons">
|
| 719 |
-
<button
|
| 720 |
-
type="button"
|
| 721 |
-
className="dev-tool-button"
|
| 722 |
-
onClick={async () => {
|
| 723 |
-
try {
|
| 724 |
-
await clearAllCache();
|
| 725 |
-
alert('Cache cleared successfully! Page will refresh.');
|
| 726 |
-
window.location.reload();
|
| 727 |
-
} catch (error) {
|
| 728 |
-
alert('Error clearing cache: ' + error.message);
|
| 729 |
-
}
|
| 730 |
-
}}
|
| 731 |
-
>
|
| 732 |
-
Clear All Cache
|
| 733 |
-
</button>
|
| 734 |
-
|
| 735 |
-
<button
|
| 736 |
-
type="button"
|
| 737 |
-
className="dev-tool-button secondary"
|
| 738 |
-
onClick={async () => {
|
| 739 |
-
try {
|
| 740 |
-
await hardRefresh();
|
| 741 |
-
} catch (error) {
|
| 742 |
-
alert('Error performing hard refresh: ' + error.message);
|
| 743 |
-
}
|
| 744 |
-
}}
|
| 745 |
-
>
|
| 746 |
-
Hard Refresh
|
| 747 |
-
</button>
|
| 748 |
-
|
| 749 |
-
<button
|
| 750 |
-
type="button"
|
| 751 |
-
className="dev-tool-button secondary"
|
| 752 |
-
onClick={async () => {
|
| 753 |
-
try {
|
| 754 |
-
await checkCacheStatus();
|
| 755 |
-
alert('Check console for cache status details');
|
| 756 |
-
} catch (error) {
|
| 757 |
-
alert('Error checking cache status: ' + error.message);
|
| 758 |
-
}
|
| 759 |
-
}}
|
| 760 |
-
>
|
| 761 |
-
Check Cache Status
|
| 762 |
-
</button>
|
| 763 |
-
</div>
|
| 764 |
-
</div>
|
| 765 |
-
|
| 766 |
-
<div className="tool-group">
|
| 767 |
-
<h4>Storage Management</h4>
|
| 768 |
-
<p className="tool-description">Clear local storage data including chat history and settings.</p>
|
| 769 |
-
|
| 770 |
-
<div className="tool-buttons">
|
| 771 |
-
<button
|
| 772 |
-
type="button"
|
| 773 |
-
className="dev-tool-button warning"
|
| 774 |
-
onClick={() => {
|
| 775 |
-
if (confirm('This will clear all local data including chat history. Are you sure?')) {
|
| 776 |
-
localStorage.clear();
|
| 777 |
-
sessionStorage.clear();
|
| 778 |
-
alert('Local storage cleared! Page will refresh.');
|
| 779 |
-
window.location.reload();
|
| 780 |
-
}
|
| 781 |
-
}}
|
| 782 |
-
>
|
| 783 |
-
Clear Local Storage
|
| 784 |
-
</button>
|
| 785 |
-
</div>
|
| 786 |
-
</div>
|
| 787 |
-
|
| 788 |
-
<div className="tool-group">
|
| 789 |
-
<h4>PWA Status</h4>
|
| 790 |
-
<p className="tool-description">PWA (Progressive Web App) functionality is currently disabled to improve page refresh behavior.</p>
|
| 791 |
-
|
| 792 |
-
<div className="pwa-info">
|
| 793 |
-
<span className="status-indicator disabled">PWA Disabled</span>
|
| 794 |
-
<small>Service worker registration is commented out in main.jsx</small>
|
| 795 |
-
</div>
|
| 796 |
-
</div>
|
| 797 |
-
</div>
|
| 798 |
-
</div>
|
| 799 |
-
|
| 800 |
<div className="settings-actions">
|
| 801 |
<button type="submit" className="save-button">Save Settings</button>
|
| 802 |
<button type="button" className="cancel-button" onClick={onCloseSettings}>Cancel</button>
|
|
|
|
| 1 |
import { useState, useEffect } from 'react';
|
|
|
|
| 2 |
|
| 3 |
function Settings({
|
| 4 |
profiles,
|
|
|
|
| 706 |
)}
|
| 707 |
</div>
|
| 708 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 709 |
<div className="settings-actions">
|
| 710 |
<button type="submit" className="save-button">Save Settings</button>
|
| 711 |
<button type="button" className="cancel-button" onClick={onCloseSettings}>Cancel</button>
|
src/index.css
CHANGED
|
@@ -2,113 +2,6 @@
|
|
| 2 |
@import './styles/mcp.css';
|
| 3 |
@import './styles/mcp-settings.css';
|
| 4 |
|
| 5 |
-
/* Developer Tools Styles */
|
| 6 |
-
.developer-tools-section {
|
| 7 |
-
background: var(--background-secondary);
|
| 8 |
-
border-radius: var(--border-radius);
|
| 9 |
-
padding: 1rem;
|
| 10 |
-
margin-top: 1rem;
|
| 11 |
-
}
|
| 12 |
-
|
| 13 |
-
.tool-group {
|
| 14 |
-
margin-bottom: 1.5rem;
|
| 15 |
-
border-bottom: 1px solid var(--border-color);
|
| 16 |
-
padding-bottom: 1rem;
|
| 17 |
-
}
|
| 18 |
-
|
| 19 |
-
.tool-group:last-child {
|
| 20 |
-
border-bottom: none;
|
| 21 |
-
margin-bottom: 0;
|
| 22 |
-
}
|
| 23 |
-
|
| 24 |
-
.tool-group h4 {
|
| 25 |
-
color: var(--text-color);
|
| 26 |
-
font-size: 1rem;
|
| 27 |
-
font-weight: 600;
|
| 28 |
-
margin-bottom: 0.5rem;
|
| 29 |
-
}
|
| 30 |
-
|
| 31 |
-
.tool-description {
|
| 32 |
-
color: var(--text-secondary);
|
| 33 |
-
font-size: 0.875rem;
|
| 34 |
-
margin-bottom: 1rem;
|
| 35 |
-
line-height: 1.5;
|
| 36 |
-
}
|
| 37 |
-
|
| 38 |
-
.tool-buttons {
|
| 39 |
-
display: flex;
|
| 40 |
-
gap: 0.75rem;
|
| 41 |
-
flex-wrap: wrap;
|
| 42 |
-
}
|
| 43 |
-
|
| 44 |
-
.dev-tool-button {
|
| 45 |
-
padding: 0.5rem 1rem;
|
| 46 |
-
border: 1px solid var(--border-color);
|
| 47 |
-
border-radius: var(--border-radius);
|
| 48 |
-
background: var(--background-primary);
|
| 49 |
-
color: var(--text-color);
|
| 50 |
-
font-size: 0.875rem;
|
| 51 |
-
cursor: pointer;
|
| 52 |
-
transition: all var(--transition-fast);
|
| 53 |
-
font-weight: 500;
|
| 54 |
-
}
|
| 55 |
-
|
| 56 |
-
.dev-tool-button:hover {
|
| 57 |
-
background: var(--background-secondary);
|
| 58 |
-
border-color: var(--primary-color);
|
| 59 |
-
color: var(--primary-color);
|
| 60 |
-
}
|
| 61 |
-
|
| 62 |
-
.dev-tool-button.secondary {
|
| 63 |
-
background: var(--background-secondary);
|
| 64 |
-
color: var(--text-secondary);
|
| 65 |
-
}
|
| 66 |
-
|
| 67 |
-
.dev-tool-button.secondary:hover {
|
| 68 |
-
background: var(--background-tertiary);
|
| 69 |
-
color: var(--text-color);
|
| 70 |
-
}
|
| 71 |
-
|
| 72 |
-
.dev-tool-button.warning {
|
| 73 |
-
background: var(--warning-light);
|
| 74 |
-
color: var(--warning-color);
|
| 75 |
-
border-color: var(--warning-color);
|
| 76 |
-
}
|
| 77 |
-
|
| 78 |
-
.dev-tool-button.warning:hover {
|
| 79 |
-
background: var(--warning-color);
|
| 80 |
-
color: white;
|
| 81 |
-
}
|
| 82 |
-
|
| 83 |
-
.pwa-info {
|
| 84 |
-
display: flex;
|
| 85 |
-
align-items: center;
|
| 86 |
-
gap: 0.75rem;
|
| 87 |
-
padding: 0.75rem;
|
| 88 |
-
background: var(--background-tertiary);
|
| 89 |
-
border-radius: var(--border-radius);
|
| 90 |
-
border: 1px solid var(--border-color);
|
| 91 |
-
}
|
| 92 |
-
|
| 93 |
-
.status-indicator {
|
| 94 |
-
padding: 0.25rem 0.75rem;
|
| 95 |
-
border-radius: 9999px;
|
| 96 |
-
font-size: 0.75rem;
|
| 97 |
-
font-weight: 600;
|
| 98 |
-
text-transform: uppercase;
|
| 99 |
-
letter-spacing: 0.05em;
|
| 100 |
-
}
|
| 101 |
-
|
| 102 |
-
.status-indicator.disabled {
|
| 103 |
-
background: var(--error-light);
|
| 104 |
-
color: var(--error-color);
|
| 105 |
-
}
|
| 106 |
-
|
| 107 |
-
.pwa-info small {
|
| 108 |
-
color: var(--text-muted);
|
| 109 |
-
font-size: 0.75rem;
|
| 110 |
-
}
|
| 111 |
-
|
| 112 |
@tailwind base;
|
| 113 |
@tailwind components;
|
| 114 |
@tailwind utilities;
|
|
|
|
| 2 |
@import './styles/mcp.css';
|
| 3 |
@import './styles/mcp-settings.css';
|
| 4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
@tailwind base;
|
| 6 |
@tailwind components;
|
| 7 |
@tailwind utilities;
|
src/main.jsx
CHANGED
|
@@ -3,13 +3,9 @@ import ReactDOM from 'react-dom/client'
|
|
| 3 |
import App from './App'
|
| 4 |
import './tailwind.css'
|
| 5 |
import './index.css'
|
| 6 |
-
// import { register as registerServiceWorker } from './serviceWorkerRegistration'
|
| 7 |
|
| 8 |
ReactDOM.createRoot(document.getElementById('root')).render(
|
| 9 |
<React.StrictMode>
|
| 10 |
<App />
|
| 11 |
</React.StrictMode>,
|
| 12 |
)
|
| 13 |
-
|
| 14 |
-
// PWA functionality disabled to allow proper refreshing
|
| 15 |
-
// registerServiceWorker()
|
|
|
|
| 3 |
import App from './App'
|
| 4 |
import './tailwind.css'
|
| 5 |
import './index.css'
|
|
|
|
| 6 |
|
| 7 |
ReactDOM.createRoot(document.getElementById('root')).render(
|
| 8 |
<React.StrictMode>
|
| 9 |
<App />
|
| 10 |
</React.StrictMode>,
|
| 11 |
)
|
|
|
|
|
|
|
|
|
src/serviceWorkerRegistration.js
DELETED
|
@@ -1,134 +0,0 @@
|
|
| 1 |
-
// This optional code is used to register a service worker.
|
| 2 |
-
// register() is not called by default.
|
| 3 |
-
|
| 4 |
-
// This lets the app load faster on subsequent visits in production, and gives
|
| 5 |
-
// it offline capabilities. However, it also means that developers (and users)
|
| 6 |
-
// will only see deployed updates on subsequent visits to a page, after all the
|
| 7 |
-
// existing tabs open on the page have been closed, since previously cached
|
| 8 |
-
// resources are updated in the background.
|
| 9 |
-
|
| 10 |
-
const isLocalhost = Boolean(
|
| 11 |
-
window.location.hostname === 'localhost' ||
|
| 12 |
-
// [::1] is the IPv6 localhost address.
|
| 13 |
-
window.location.hostname === '[::1]' ||
|
| 14 |
-
// 127.0.0.0/8 are considered localhost for IPv4.
|
| 15 |
-
window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)
|
| 16 |
-
);
|
| 17 |
-
|
| 18 |
-
export function register(config) {
|
| 19 |
-
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
| 20 |
-
// The URL constructor is available in all browsers that support SW.
|
| 21 |
-
const publicUrl = new URL(import.meta.env.BASE_URL, window.location.href);
|
| 22 |
-
if (publicUrl.origin !== window.location.origin) {
|
| 23 |
-
// Our service worker won't work if BASE_URL is on a different origin
|
| 24 |
-
// from what our page is served on. This might happen if a CDN is used to
|
| 25 |
-
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
| 26 |
-
return;
|
| 27 |
-
}
|
| 28 |
-
|
| 29 |
-
window.addEventListener('load', () => {
|
| 30 |
-
const swUrl = `${import.meta.env.BASE_URL}sw.js`;
|
| 31 |
-
|
| 32 |
-
if (isLocalhost) {
|
| 33 |
-
// This is running on localhost. Let's check if a service worker still exists or not.
|
| 34 |
-
checkValidServiceWorker(swUrl, config);
|
| 35 |
-
|
| 36 |
-
// Add some additional logging to localhost, pointing developers to the
|
| 37 |
-
// service worker/PWA documentation.
|
| 38 |
-
navigator.serviceWorker.ready.then(() => {
|
| 39 |
-
console.log(
|
| 40 |
-
'This web app is being served cache-first by a service ' +
|
| 41 |
-
'worker. To learn more, visit https://cra.link/PWA'
|
| 42 |
-
);
|
| 43 |
-
});
|
| 44 |
-
} else {
|
| 45 |
-
// Is not localhost. Just register service worker
|
| 46 |
-
registerValidSW(swUrl, config);
|
| 47 |
-
}
|
| 48 |
-
});
|
| 49 |
-
}
|
| 50 |
-
}
|
| 51 |
-
|
| 52 |
-
function registerValidSW(swUrl, config) {
|
| 53 |
-
navigator.serviceWorker
|
| 54 |
-
.register(swUrl)
|
| 55 |
-
.then((registration) => {
|
| 56 |
-
registration.onupdatefound = () => {
|
| 57 |
-
const installingWorker = registration.installing;
|
| 58 |
-
if (installingWorker == null) {
|
| 59 |
-
return;
|
| 60 |
-
}
|
| 61 |
-
installingWorker.onstatechange = () => {
|
| 62 |
-
if (installingWorker.state === 'installed') {
|
| 63 |
-
if (navigator.serviceWorker.controller) {
|
| 64 |
-
// At this point, the updated precached content has been fetched,
|
| 65 |
-
// but the previous service worker will still serve the older
|
| 66 |
-
// content until all client tabs are closed.
|
| 67 |
-
console.log(
|
| 68 |
-
'New content is available and will be used when all ' +
|
| 69 |
-
'tabs for this page are closed. See https://cra.link/PWA.'
|
| 70 |
-
);
|
| 71 |
-
|
| 72 |
-
// Execute callback
|
| 73 |
-
if (config && config.onUpdate) {
|
| 74 |
-
config.onUpdate(registration);
|
| 75 |
-
}
|
| 76 |
-
} else {
|
| 77 |
-
// At this point, everything has been precached.
|
| 78 |
-
// It's the perfect time to display a
|
| 79 |
-
// "Content is cached for offline use." message.
|
| 80 |
-
console.log('Content is cached for offline use.');
|
| 81 |
-
|
| 82 |
-
// Execute callback
|
| 83 |
-
if (config && config.onSuccess) {
|
| 84 |
-
config.onSuccess(registration);
|
| 85 |
-
}
|
| 86 |
-
}
|
| 87 |
-
}
|
| 88 |
-
};
|
| 89 |
-
};
|
| 90 |
-
})
|
| 91 |
-
.catch((error) => {
|
| 92 |
-
console.error('Error during service worker registration:', error);
|
| 93 |
-
});
|
| 94 |
-
}
|
| 95 |
-
|
| 96 |
-
function checkValidServiceWorker(swUrl, config) {
|
| 97 |
-
// Check if the service worker can be found. If it can't reload the page.
|
| 98 |
-
fetch(swUrl, {
|
| 99 |
-
headers: { 'Service-Worker': 'script' },
|
| 100 |
-
})
|
| 101 |
-
.then((response) => {
|
| 102 |
-
// Ensure service worker exists, and that we really are getting a JS file.
|
| 103 |
-
const contentType = response.headers.get('content-type');
|
| 104 |
-
if (
|
| 105 |
-
response.status === 404 ||
|
| 106 |
-
(contentType != null && contentType.indexOf('javascript') === -1)
|
| 107 |
-
) {
|
| 108 |
-
// No service worker found. Probably a different app. Reload the page.
|
| 109 |
-
navigator.serviceWorker.ready.then((registration) => {
|
| 110 |
-
registration.unregister().then(() => {
|
| 111 |
-
window.location.reload();
|
| 112 |
-
});
|
| 113 |
-
});
|
| 114 |
-
} else {
|
| 115 |
-
// Service worker found. Proceed as normal.
|
| 116 |
-
registerValidSW(swUrl, config);
|
| 117 |
-
}
|
| 118 |
-
})
|
| 119 |
-
.catch(() => {
|
| 120 |
-
console.log('No internet connection found. App is running in offline mode.');
|
| 121 |
-
});
|
| 122 |
-
}
|
| 123 |
-
|
| 124 |
-
export function unregister() {
|
| 125 |
-
if ('serviceWorker' in navigator) {
|
| 126 |
-
navigator.serviceWorker.ready
|
| 127 |
-
.then((registration) => {
|
| 128 |
-
registration.unregister();
|
| 129 |
-
})
|
| 130 |
-
.catch((error) => {
|
| 131 |
-
console.error(error.message);
|
| 132 |
-
});
|
| 133 |
-
}
|
| 134 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/utils/clearCache.js
DELETED
|
@@ -1,68 +0,0 @@
|
|
| 1 |
-
// Utility to clear PWA cache and service worker
|
| 2 |
-
|
| 3 |
-
export async function clearAllCache() {
|
| 4 |
-
try {
|
| 5 |
-
// Unregister all service workers
|
| 6 |
-
if ('serviceWorker' in navigator) {
|
| 7 |
-
const registrations = await navigator.serviceWorker.getRegistrations();
|
| 8 |
-
for (let registration of registrations) {
|
| 9 |
-
await registration.unregister();
|
| 10 |
-
console.log('Service worker unregistered:', registration);
|
| 11 |
-
}
|
| 12 |
-
}
|
| 13 |
-
|
| 14 |
-
// Clear all caches
|
| 15 |
-
if ('caches' in window) {
|
| 16 |
-
const cacheNames = await caches.keys();
|
| 17 |
-
await Promise.all(
|
| 18 |
-
cacheNames.map(cacheName => {
|
| 19 |
-
console.log('Deleting cache:', cacheName);
|
| 20 |
-
return caches.delete(cacheName);
|
| 21 |
-
})
|
| 22 |
-
);
|
| 23 |
-
}
|
| 24 |
-
|
| 25 |
-
// Clear localStorage and sessionStorage
|
| 26 |
-
localStorage.clear();
|
| 27 |
-
sessionStorage.clear();
|
| 28 |
-
|
| 29 |
-
console.log('All cache and storage cleared!');
|
| 30 |
-
return true;
|
| 31 |
-
} catch (error) {
|
| 32 |
-
console.error('Error clearing cache:', error);
|
| 33 |
-
return false;
|
| 34 |
-
}
|
| 35 |
-
}
|
| 36 |
-
|
| 37 |
-
export async function hardRefresh() {
|
| 38 |
-
await clearAllCache();
|
| 39 |
-
|
| 40 |
-
// Force hard refresh
|
| 41 |
-
if (typeof window !== 'undefined') {
|
| 42 |
-
// Try different hard refresh methods
|
| 43 |
-
if (window.location.reload) {
|
| 44 |
-
window.location.reload(true); // Force reload
|
| 45 |
-
} else {
|
| 46 |
-
window.location.href = window.location.href;
|
| 47 |
-
}
|
| 48 |
-
}
|
| 49 |
-
}
|
| 50 |
-
|
| 51 |
-
// Debug function to check cache status
|
| 52 |
-
export async function checkCacheStatus() {
|
| 53 |
-
if ('caches' in window) {
|
| 54 |
-
const cacheNames = await caches.keys();
|
| 55 |
-
console.log('Active caches:', cacheNames);
|
| 56 |
-
|
| 57 |
-
for (const cacheName of cacheNames) {
|
| 58 |
-
const cache = await caches.open(cacheName);
|
| 59 |
-
const requests = await cache.keys();
|
| 60 |
-
console.log(`Cache ${cacheName} contains:`, requests.map(req => req.url));
|
| 61 |
-
}
|
| 62 |
-
}
|
| 63 |
-
|
| 64 |
-
if ('serviceWorker' in navigator) {
|
| 65 |
-
const registrations = await navigator.serviceWorker.getRegistrations();
|
| 66 |
-
console.log('Active service workers:', registrations);
|
| 67 |
-
}
|
| 68 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
test-xsai.js
DELETED
|
@@ -1,94 +0,0 @@
|
|
| 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);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|