feat: consolidate docs, backend/session infra, and settings updates

This commit is contained in:
Dwindi Ramadhana
2026-05-28 00:58:20 +07:00
parent 2424acf726
commit 44e06eed88
102 changed files with 35423 additions and 11181 deletions

View File

@@ -1,7 +0,0 @@
# Ignore node_modules in local backend package
agentic-writer-local-backend/node_modules/
agentic-writer-local-backend/proxy.log
agentic-writer-local-backend/proxy.pid
# Keep the distributable ZIP
!agentic-writer-local-backend.zip

217
downloads/README.md Normal file
View File

@@ -0,0 +1,217 @@
# Agentic Writer Local Backend
Run unlimited AI content generation on your own machine using your Claude CLI + Z.ai/Anthropic account.
## Prerequisites
Before starting, ensure you have:
-**Claude CLI** installed and configured
- Get it: [https://claude.ai/code](https://claude.ai/code) or [https://z.ai](https://z.ai)
- Verify: `claude --version` or `which claude`
-**Node.js 18+** installed
- Download: [https://nodejs.org](https://nodejs.org)
- Verify: `node --version`
-**Z.ai Coding Plan** or **Anthropic API key** configured in Claude CLI
## Quick Start
### 1. Extract Package
```bash
unzip agentic-writer-local-backend.zip
cd agentic-writer-local-backend
```
### 2. Start the Proxy
```bash
chmod +x *.sh
./start-proxy.sh
```
You'll see:
```
═══════════════════════════════════════════════════
✅ Local Backend Running!
═══════════════════════════════════════════════════
Your Configuration:
Base URL: http://192.168.1.105:8080
API Key: dummy
Model: claude-local
```
### 3. Configure WordPress Plugin
1. Open **WP Admin****Agentic Writer****Settings****Local Backend**
2. Paste the **Base URL** shown above
3. API Key: `dummy`
4. Click **Test Connection** → should show ✅
5. Start generating content!
## Commands
```bash
./start-proxy.sh # Start proxy (runs in background)
./stop-proxy.sh # Stop proxy
./test-connection.sh # Test if proxy responds
./get-local-ip.sh # Find your local IP address
tail -f proxy.log # View real-time logs
```
## Firewall Setup
The proxy needs to accept connections from your WordPress site.
### macOS
1. **System Settings****Network****Firewall**
2. Click **Options****Add** → Select `node`
3. Set to **Allow incoming connections**
### Linux (ufw)
```bash
sudo ufw allow 8080/tcp
sudo ufw reload
```
### Windows
1. **Windows Defender Firewall****Advanced Settings**
2. **Inbound Rules****New Rule**
3. **Port** → TCP **8080****Allow**
## How It Works
```
WordPress Plugin → HTTP POST → Local Proxy (port 8080)
Spawns Claude CLI
Returns AI Response
```
**Benefits:**
- 🆓 **Free**: Uses your existing Z.ai/Anthropic subscription
- 🔒 **Private**: Content never leaves your network
-**Fast**: LAN latency (~50-200ms)
- 🚀 **Unlimited**: No rate limits, no token counting
## Troubleshooting
See [TROUBLESHOOTING.md](TROUBLESHOOTING.md) for detailed solutions.
### Quick Fixes
**"Connection failed" in plugin:**
```bash
# Check proxy is running
ps aux | grep claude-proxy
# Restart if needed
./stop-proxy.sh && ./start-proxy.sh
```
**"Claude CLI not found":**
```bash
# Verify Claude is installed
which claude
claude --version
# Test Claude works
echo "Hello" | claude
```
**"Wrong IP address":**
```bash
# Find your correct IP
./get-local-ip.sh
# Or manually:
# macOS: ipconfig getifaddr en0
# Linux: ip route get 1 | awk '{print $7}'
```
**Port 8080 already in use:**
```bash
# Find what's using it
lsof -i :8080
# Change port (edit claude-proxy.js)
PORT=9000 node claude-proxy.js
# Update plugin Base URL to: http://your-ip:9000
```
## Security Notes
- Proxy binds to `0.0.0.0` (all network interfaces) for LAN access
- No authentication by design (LAN trust model)
- All request prompts are logged to `proxy.log`
- For internet exposure, use ngrok/reverse proxy with authentication
## Environment Variables
```bash
# Use different port (default: 8080)
PORT=9000 ./start-proxy.sh
# Production mode
NODE_ENV=production
# Brave Search API (for web search capability)
export BRAVE_SEARCH_API_KEY="your-brave-api-key"
```
### Enabling Web Search (Brave Search)
To enable web search in your AI responses:
1. **Get a Brave Search API key** from [https://brave.com/search/api/](https://brave.com/search/api/)
2. **Configure it in one of these ways:**
**Option 1: Add to `.env` file (recommended for this proxy)**
```bash
echo 'BRAVE_SEARCH_API_KEY="BSA03Yj-your-key-here"' > .env
```
**Option 2: Add to Claude Code settings**
Add to `~/.claude/settings.json`:
```json
{
"env": {
"BRAVE_SEARCH_API_KEY": "your-key-here"
}
}
```
**Option 3: Add to shell profile**
```bash
export BRAVE_SEARCH_API_KEY="your-key-here"
```
3. **Restart the proxy**:
```bash
./stop-proxy.sh && ./start-proxy.sh
```
When the proxy starts, you should see:
```
Brave Search:
API Key: CONFIGURED
```
**Note:** Web search must also be enabled in the WordPress plugin settings (Agentic Writer → Settings → General → Search → Enable). The plugin will automatically use search results when planning or researching topics.
## Support
- **Documentation**: [Plugin Docs](https://github.com/your/plugin)
- **Issues**: [GitHub Issues](https://github.com/your/plugin/issues)
- **Community**: [Discord](https://discord.gg/your-server)
## License
GPL-2.0+ - Same as WP Agentic Writer plugin

View File

@@ -0,0 +1,339 @@
# Troubleshooting Guide
Common issues and solutions for Agentic Writer Local Backend.
## Connection Issues
### "Connection timeout" in Plugin
**Symptoms:**
- Plugin shows "Connection timeout" error
- Test connection fails
**Solutions:**
1. **Check proxy is running:**
```bash
ps aux | grep claude-proxy
```
2. **Restart proxy:**
```bash
./stop-proxy.sh
./start-proxy.sh
```
3. **Check logs:**
```bash
tail -f proxy.log
```
4. **Verify IP address:**
```bash
./get-local-ip.sh
```
### "Connection refused"
**Cause:** Proxy not running or wrong IP
**Solutions:**
1. **Start proxy:**
```bash
./start-proxy.sh
```
2. **Check firewall:**
- macOS: System Settings → Network → Firewall → Allow Node.js
- Linux: `sudo ufw allow 8080/tcp`
- Windows: Defender Firewall → Allow port 8080
3. **Test locally first:**
```bash
curl http://localhost:8080/ping
# Should return: pong
```
## Claude CLI Issues
### "Claude CLI not found"
**Verify installation:**
```bash
which claude
# macOS: /opt/homebrew/bin/claude or /usr/local/bin/claude
# Linux: ~/.local/bin/claude or /usr/bin/claude
```
**Fix PATH:**
```bash
# Add to ~/.zshrc or ~/.bashrc
export PATH="/opt/homebrew/bin:$PATH"
source ~/.zshrc
```
**Reinstall Claude CLI:**
- Visit: [https://claude.ai/code](https://claude.ai/code)
- Follow installation instructions
### "No response from Claude"
**Test Claude manually:**
```bash
echo "Hello, reply with: Test successful" | claude
```
**Check authentication:**
```bash
claude --version
# Should show version and auth status
```
**Reconfigure Claude:**
- Check Z.ai account: [https://z.ai](https://z.ai)
- Or Anthropic API key setup
## Network Issues
### Wrong IP Address Detected
**Find correct IP:**
```bash
# macOS
ipconfig getifaddr en0 # WiFi
ipconfig getifaddr en1 # Ethernet
# Linux
ip route get 1 | awk '{print $7}'
hostname -I
# Windows
ipconfig
# Look for "IPv4 Address" under active adapter
```
**Update plugin settings:**
- Use the correct IP in Base URL: `http://CORRECT-IP:8080`
### Port 8080 Already in Use
**Find what's using it:**
```bash
lsof -i :8080
# or
netstat -anp | grep 8080
```
**Change port:**
1. Edit `claude-proxy.js`:
```javascript
const PORT = process.env.PORT || 9000; // Change 8080 to 9000
```
2. Restart proxy:
```bash
./stop-proxy.sh
PORT=9000 ./start-proxy.sh
```
3. Update plugin Base URL: `http://your-ip:9000`
## Performance Issues
### Slow Response Times
**Normal latency:**
- Local network: 50-200ms
- Claude CLI processing: 2-30 seconds depending on prompt
**If consistently slow:**
1. **Check network:**
```bash
ping 192.168.1.105 # Your proxy IP
```
2. **Monitor logs:**
```bash
tail -f proxy.log
```
3. **Check machine resources:**
- CPU usage: Claude CLI is CPU-intensive
- Memory: Ensure sufficient RAM available
### Proxy Crashes
**Check logs:**
```bash
cat proxy.log | tail -50
```
**Common causes:**
- Out of memory: Close other applications
- Claude CLI timeout: Increase timeout in `claude-proxy.js`
- Malformed requests: Check plugin version compatibility
**Restart with clean state:**
```bash
./stop-proxy.sh
rm proxy.log
./start-proxy.sh
```
## Plugin Integration Issues
### "Invalid response format"
**Cause:** Claude response doesn't match expected JSON format
**Debug:**
1. Check `proxy.log` for actual Claude output
2. Test manually:
```bash
curl -X POST http://localhost:8080/v1/messages \
-H "Content-Type: application/json" \
-d '{"messages":[{"role":"user","content":"Hello"}]}'
```
3. Update Claude CLI if outdated:
```bash
claude --version
# Upgrade if needed
```
### Cost Tracking Shows $0
**Expected behavior:** Local backend is free, plugin should show `$0.00 (Local)`
**If concerned:**
- This is correct - local backend has no API costs
- Dashboard should show "X requests local (free)"
## Advanced Troubleshooting
### Enable Debug Logging
Edit `claude-proxy.js`:
```javascript
const DEBUG = true; // Add at top of file
// In /v1/messages handler:
if (DEBUG) {
console.log('Full request:', JSON.stringify(req.body, null, 2));
console.log('Full response:', output);
}
```
### Test with curl
**Ping:**
```bash
curl http://localhost:8080/ping
# Expected: pong
```
**Inference:**
```bash
curl -X POST http://localhost:8080/v1/messages \
-H "Content-Type: application/json" \
-d '{
"messages": [
{"role": "user", "content": "Reply with: Test successful"}
]
}'
```
**Expected response:**
```json
{
"id": "local-1234567890",
"object": "chat.completion",
"model": "claude-local",
"choices": [{
"message": {
"content": "Test successful"
}
}]
}
```
### Permissions Issues (macOS)
**Make scripts executable:**
```bash
chmod +x start-proxy.sh stop-proxy.sh test-connection.sh get-local-ip.sh
```
**If "permission denied":**
```bash
# Check file permissions
ls -la *.sh
# Reset if needed
chmod 755 *.sh
```
## Still Having Issues?
1. **Check system requirements:**
- Node.js 18+: `node --version`
- Claude CLI installed: `which claude`
- Sufficient disk space: `df -h`
2. **Collect diagnostic info:**
```bash
echo "Node version:" $(node --version)
echo "Claude path:" $(which claude)
echo "Local IP:" $(./get-local-ip.sh)
echo "Proxy status:" $(ps aux | grep claude-proxy)
tail -20 proxy.log
```
3. **Reset everything:**
```bash
./stop-proxy.sh
rm -rf node_modules proxy.log proxy.pid
npm install
./start-proxy.sh
```
4. **Get help:**
- GitHub Issues: [Report Bug](https://github.com/your/plugin/issues)
- Discord Community: [Join Chat](https://discord.gg/your-server)
- Include: OS, Node version, Claude CLI version, error logs
## Environment-Specific Notes
### macOS
- Default Claude path: `/opt/homebrew/bin/claude`
- Firewall: System Settings → Network → Firewall
- IP detection: `ipconfig getifaddr en0`
### Linux
- Default Claude path: `~/.local/bin/claude`
- Firewall: `sudo ufw allow 8080/tcp`
- IP detection: `ip route get 1 | awk '{print $7}'`
### Windows
- Claude path varies, check `where claude`
- Firewall: Windows Defender → Allow port 8080
- IP detection: `ipconfig` (look for IPv4)
- Scripts: Use Git Bash or WSL to run `.sh` scripts
## Security Best Practices
1. **LAN only:** Don't expose proxy to internet without authentication
2. **Firewall:** Restrict to specific IPs if on shared network
3. **Logs:** `proxy.log` contains all prompts - review periodically
4. **Updates:** Keep Node.js and Claude CLI updated
---
**Last Updated:** 2025-02-27
**Version:** 1.0.0

View File

@@ -1,122 +0,0 @@
const express = require('express');
const { spawn } = require('child_process');
const app = express();
app.use(express.json());
// Health check endpoint
app.get('/ping', (req, res) => {
res.send('pong');
});
// Main inference endpoint (OpenAI-compatible format)
app.post('/v1/messages', async (req, res) => {
const { messages } = req.body;
if (!messages || !Array.isArray(messages) || messages.length === 0) {
return res.status(400).json({
error: {
message: 'Invalid request: messages array required'
}
});
}
// Extract the last user message as the prompt
const lastMessage = messages[messages.length - 1];
const prompt = lastMessage.content;
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log('Request from:', req.ip);
console.log('Prompt length:', prompt.length, 'chars');
console.log('Prompt preview:', prompt.substring(0, 150) + '...');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
// Spawn Claude CLI process
const claude = spawn('claude', [], {
stdio: ['pipe', 'pipe', 'pipe']
});
let output = '';
let errorOutput = '';
claude.stdout.on('data', (data) => {
output += data.toString();
process.stdout.write('.');
});
claude.stderr.on('data', (data) => {
errorOutput += data.toString();
console.error('Claude stderr:', data.toString());
});
claude.on('close', (code) => {
console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log('Claude exit code:', code);
console.log('Response length:', output.length, 'chars');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
if (code !== 0 || !output.trim()) {
return res.status(500).json({
error: {
message: 'Claude CLI error',
details: errorOutput || 'No response from Claude'
}
});
}
// Return OpenAI-compatible response format
res.json({
id: 'local-' + Date.now(),
object: 'chat.completion',
created: Math.floor(Date.now() / 1000),
model: 'claude-local',
choices: [{
index: 0,
message: {
role: 'assistant',
content: output.trim()
},
finish_reason: 'stop'
}],
usage: {
prompt_tokens: 0,
completion_tokens: 0,
total_tokens: 0
}
});
});
claude.on('error', (err) => {
console.error('Failed to spawn Claude CLI:', err);
res.status(500).json({
error: {
message: 'Failed to spawn Claude CLI',
details: err.message
}
});
});
// Send prompt to Claude after brief pause
setTimeout(() => {
claude.stdin.write(prompt + '\n');
claude.stdin.end();
}, 100);
});
const PORT = process.env.PORT || 8080;
app.listen(PORT, '0.0.0.0', () => {
console.log('═══════════════════════════════════════════════════');
console.log('🚀 Agentic Writer Local Backend Started!');
console.log('═══════════════════════════════════════════════════');
console.log(`Local: http://localhost:${PORT}`);
console.log(`Network: http://YOUR-IP:${PORT}`);
console.log('');
console.log('Plugin Configuration:');
console.log(` Base URL: http://YOUR-IP:${PORT}`);
console.log(` API Key: dummy`);
console.log(` Model: claude-local`);
console.log('');
console.log('Health check: GET /ping');
console.log('Inference: POST /v1/messages');
console.log('═══════════════════════════════════════════════════');
});

279
downloads/claude-proxy.js Normal file
View File

@@ -0,0 +1,279 @@
const express = require('express');
const { spawn } = require('child_process');
const https = require('https');
const http = require('http');
const fs = require('fs');
const path = require('path');
const app = express();
app.use(express.json());
// Try multiple sources for Brave API Key (in order of priority):
// 1. Environment variable
// 2. .env file in proxy directory
// 3. ~/.claude/settings.json (Claude Code config)
function getBraveApiKey() {
// 1. Check environment variable first
if (process.env.BRAVE_SEARCH_API_KEY) {
return process.env.BRAVE_SEARCH_API_KEY;
}
// 2. Check .env file in proxy directory
const envPath = path.join(__dirname, '.env');
if (fs.existsSync(envPath)) {
const envContent = fs.readFileSync(envPath, 'utf8');
const match = envContent.match(/BRAVE_SEARCH_API_KEY\s*=\s*(.+)/m);
if (match) {
return match[1].trim();
}
}
// 3. Check Claude Code settings.json
const claudeSettingsPath = path.join(process.env.HOME || '/root', '.claude', 'settings.json');
if (fs.existsSync(claudeSettingsPath)) {
try {
const settings = JSON.parse(fs.readFileSync(claudeSettingsPath, 'utf8'));
if (settings.env?.BRAVE_SEARCH_API_KEY) {
return settings.env.BRAVE_SEARCH_API_KEY;
}
} catch (e) {
// Ignore JSON parse errors
}
}
return '';
}
// Health check endpoint
app.get('/ping', (req, res) => {
const status = {
status: 'pong',
braveSearchConfigured: !!BRAVE_API_KEY,
timestamp: new Date().toISOString()
};
res.json(status);
});
// Main inference endpoint (OpenAI-compatible format)
app.post('/v1/messages', async (req, res) => {
const { messages, stream } = req.body;
if (!messages || !Array.isArray(messages) || messages.length === 0) {
return res.status(400).json({
error: {
message: 'Invalid request: messages array required'
}
});
}
// Check if web search is requested (via X-Search-Enabled header)
const webSearchEnabled = req.headers['x-search-enabled'] === 'true';
const searchQuery = req.headers['x-search-query'] || '';
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log('Request from:', req.ip);
console.log('Web Search:', webSearchEnabled ? 'ENABLED' : 'disabled');
if (searchQuery) {
console.log('Search Query:', searchQuery.substring(0, 100) + '...');
}
const braveApiKey = getBraveApiKey();
console.log('Brave API Key:', braveApiKey ? 'CONFIGURED' : 'NOT SET');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
// If web search is enabled and we have a query, fetch search results first
let searchContext = '';
if (webSearchEnabled && searchQuery && braveApiKey) {
console.log('Fetching web search results...');
try {
searchContext = await fetchBraveSearchResults(searchQuery, braveApiKey);
console.log('Search results fetched:', searchContext.length, 'chars');
} catch (err) {
console.error('Search error:', err.message);
}
}
// Build conversation context from messages array
// Include previous messages for context continuity
let conversationPrompt = '';
for (const msg of messages) {
const role = msg.role === 'assistant' ? 'Assistant' : 'User';
conversationPrompt += `${role}: ${msg.content}\n\n`;
}
let prompt = conversationPrompt.trim();
// Prepend search context if available
if (searchContext) {
prompt = `WEB SEARCH RESULTS:\n${searchContext}\n\n---\n\nUSER QUERY:\n${prompt}\n\nPlease answer based on the search results above when relevant.`;
}
console.log('Prompt length:', prompt.length, 'chars');
console.log('Prompt preview:', prompt.substring(0, 150) + '...');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
// Spawn Claude CLI process
const claude = spawn('claude', [], {
stdio: ['pipe', 'pipe', 'pipe']
});
let output = '';
let errorOutput = '';
claude.stdout.on('data', (data) => {
output += data.toString();
process.stdout.write('.');
});
claude.stderr.on('data', (data) => {
errorOutput += data.toString();
console.error('Claude stderr:', data.toString());
});
claude.on('close', (code) => {
console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log('Claude exit code:', code);
console.log('Response length:', output.length, 'chars');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
if (code !== 0 || !output.trim()) {
return res.status(500).json({
error: {
message: 'Claude CLI error',
details: errorOutput || 'No response from Claude'
}
});
}
// Return OpenAI-compatible response format
res.json({
id: 'local-' + Date.now(),
object: 'chat.completion',
created: Math.floor(Date.now() / 1000),
model: 'claude-local',
choices: [{
index: 0,
message: {
role: 'assistant',
content: output.trim()
},
finish_reason: 'stop'
}],
usage: {
prompt_tokens: 0,
completion_tokens: 0,
total_tokens: 0
}
});
});
claude.on('error', (err) => {
console.error('Failed to spawn Claude CLI:', err);
res.status(500).json({
error: {
message: 'Failed to spawn Claude CLI',
details: err.message
}
});
});
// Send prompt to Claude after brief pause
setTimeout(() => {
claude.stdin.write(prompt + '\n');
claude.stdin.end();
}, 100);
});
/**
* Fetch search results from Brave Search API
*/
async function fetchBraveSearchResults(query, apiKey, count = 5) {
return new Promise((resolve, reject) => {
const encodedQuery = encodeURIComponent(query);
const url = `https://api.search.brave.com/res/v1/web/search?q=${encodedQuery}&count=${count}`;
const options = {
headers: {
'Accept': 'application/json',
'X-Subscription-Token': apiKey
}
};
const protocol = url.startsWith('https') ? https : http;
const request = protocol.get(url, options, (response) => {
let data = '';
response.on('data', (chunk) => {
data += chunk;
});
response.on('end', () => {
if (response.statusCode !== 200) {
return reject(new Error(`Brave API error: ${response.statusCode}`));
}
try {
const json = JSON.parse(data);
const results = json.web?.results || [];
if (results.length === 0) {
return resolve('No search results found.');
}
// Format results for LLM consumption
let formatted = 'Search Results:\n\n';
results.forEach((result, i) => {
formatted += `${i + 1}. **${result.title}**\n`;
formatted += ` URL: ${result.url}\n`;
if (result.description) {
formatted += ` Summary: ${result.description}\n`;
}
formatted += '\n';
});
resolve(formatted);
} catch (err) {
reject(new Error('Failed to parse Brave response'));
}
});
});
request.on('error', (err) => {
reject(err);
});
request.setTimeout(10000, () => {
request.destroy();
reject(new Error('Brave search timeout'));
});
});
}
const PORT = process.env.PORT || 8080;
app.listen(PORT, '0.0.0.0', () => {
const braveApiKey = getBraveApiKey();
console.log('═══════════════════════════════════════════════════');
console.log('🚀 Agentic Writer Local Backend v1.1.0');
console.log('═══════════════════════════════════════════════════');
console.log(`Local: http://localhost:${PORT}`);
console.log(`Network: http://YOUR-IP:${PORT}`);
console.log('');
console.log('Plugin Configuration:');
console.log(` Base URL: http://YOUR-IP:${PORT}`);
console.log(` API Key: dummy`);
console.log(` Model: claude-local`);
console.log('');
console.log('Brave Search:');
console.log(` API Key: ${braveApiKey ? 'CONFIGURED' : 'NOT SET'}`);
console.log('');
console.log('Web search works when Brave API key is found from:');
console.log(' 1. Environment: export BRAVE_SEARCH_API_KEY="key"');
console.log(' 2. .env file: BRAVE_SEARCH_API_KEY=key');
console.log(' 3. ~/.claude/settings.json env.BRAVE_SEARCH_API_KEY');
console.log('');
console.log('Restart proxy after adding key: ./stop-proxy.sh && ./start-proxy.sh');
console.log('');
console.log('Health check: GET /ping');
console.log('Inference: POST /v1/messages');
console.log('═══════════════════════════════════════════════════');
});

828
downloads/package-lock.json generated Normal file
View File

@@ -0,0 +1,828 @@
{
"name": "agentic-writer-local-backend",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "agentic-writer-local-backend",
"version": "1.0.0",
"license": "GPL-2.0+",
"dependencies": {
"express": "^4.18.2"
}
},
"node_modules/accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
"license": "MIT",
"dependencies": {
"mime-types": "~2.1.34",
"negotiator": "0.6.3"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
"license": "MIT"
},
"node_modules/body-parser": {
"version": "1.20.5",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz",
"integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==",
"license": "MIT",
"dependencies": {
"bytes": "~3.1.2",
"content-type": "~1.0.5",
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "~1.2.0",
"http-errors": "~2.0.1",
"iconv-lite": "~0.4.24",
"on-finished": "~2.4.1",
"qs": "~6.15.1",
"raw-body": "~2.5.3",
"type-is": "~1.6.18",
"unpipe": "~1.0.0"
},
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
}
},
"node_modules/bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/call-bound": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"get-intrinsic": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/content-disposition": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
"integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
"license": "MIT",
"dependencies": {
"safe-buffer": "5.2.1"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/content-type": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie-signature": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz",
"integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==",
"license": "MIT"
},
"node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
},
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/destroy": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
"license": "MIT",
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
}
},
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
"es-errors": "^1.3.0",
"gopd": "^1.2.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
"license": "MIT"
},
"node_modules/encodeurl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
"integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-object-atoms": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
"license": "MIT"
},
"node_modules/etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/express": {
"version": "4.22.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz",
"integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==",
"license": "MIT",
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
"body-parser": "~1.20.5",
"content-disposition": "~0.5.4",
"content-type": "~1.0.4",
"cookie": "~0.7.1",
"cookie-signature": "~1.0.6",
"debug": "2.6.9",
"depd": "2.0.0",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"finalhandler": "~1.3.1",
"fresh": "~0.5.2",
"http-errors": "~2.0.0",
"merge-descriptors": "1.0.3",
"methods": "~1.1.2",
"on-finished": "~2.4.1",
"parseurl": "~1.3.3",
"path-to-regexp": "~0.1.12",
"proxy-addr": "~2.0.7",
"qs": "~6.15.1",
"range-parser": "~1.2.1",
"safe-buffer": "5.2.1",
"send": "~0.19.0",
"serve-static": "~1.16.2",
"setprototypeof": "1.2.0",
"statuses": "~2.0.1",
"type-is": "~1.6.18",
"utils-merge": "1.0.1",
"vary": "~1.1.2"
},
"engines": {
"node": ">= 0.10.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/finalhandler": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz",
"integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==",
"license": "MIT",
"dependencies": {
"debug": "2.6.9",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"on-finished": "~2.4.1",
"parseurl": "~1.3.3",
"statuses": "~2.0.2",
"unpipe": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-intrinsic": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"es-define-property": "^1.0.1",
"es-errors": "^1.3.0",
"es-object-atoms": "^1.1.1",
"function-bind": "^1.1.2",
"get-proto": "^1.0.1",
"gopd": "^1.2.0",
"has-symbols": "^1.1.0",
"hasown": "^2.0.2",
"math-intrinsics": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"license": "MIT",
"dependencies": {
"dunder-proto": "^1.0.1",
"es-object-atoms": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/hasown": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz",
"integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==",
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/http-errors": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
"integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
"license": "MIT",
"dependencies": {
"depd": "~2.0.0",
"inherits": "~2.0.4",
"setprototypeof": "~1.2.0",
"statuses": "~2.0.2",
"toidentifier": "~1.0.1"
},
"engines": {
"node": ">= 0.8"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
"node_modules/ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
"license": "MIT",
"engines": {
"node": ">= 0.10"
}
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/merge-descriptors": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
"integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
"license": "MIT",
"bin": {
"mime": "cli.js"
},
"engines": {
"node": ">=4"
}
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT"
},
"node_modules/negotiator": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/object-inspect": {
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
"integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/on-finished": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
"integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
"license": "MIT",
"dependencies": {
"ee-first": "1.1.1"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/path-to-regexp": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz",
"integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==",
"license": "MIT"
},
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
"integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
"license": "MIT",
"dependencies": {
"forwarded": "0.2.0",
"ipaddr.js": "1.9.1"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/qs": {
"version": "6.15.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz",
"integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.1.0"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/range-parser": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/raw-body": {
"version": "2.5.3",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz",
"integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==",
"license": "MIT",
"dependencies": {
"bytes": "~3.1.2",
"http-errors": "~2.0.1",
"iconv-lite": "~0.4.24",
"unpipe": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT"
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"license": "MIT"
},
"node_modules/send": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz",
"integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==",
"license": "MIT",
"dependencies": {
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"fresh": "~0.5.2",
"http-errors": "~2.0.1",
"mime": "1.6.0",
"ms": "2.1.3",
"on-finished": "~2.4.1",
"range-parser": "~1.2.1",
"statuses": "~2.0.2"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/send/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/serve-static": {
"version": "1.16.3",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz",
"integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==",
"license": "MIT",
"dependencies": {
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"parseurl": "~1.3.3",
"send": "~0.19.1"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
"license": "ISC"
},
"node_modules/side-channel": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
"integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.3",
"side-channel-list": "^1.0.0",
"side-channel-map": "^1.0.1",
"side-channel-weakmap": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-list": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz",
"integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.4"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-map": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
"integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.5",
"object-inspect": "^1.13.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-weakmap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
"integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.5",
"object-inspect": "^1.13.3",
"side-channel-map": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/statuses": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
"integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
"license": "MIT",
"engines": {
"node": ">=0.6"
}
},
"node_modules/type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
"license": "MIT",
"dependencies": {
"media-typer": "0.3.0",
"mime-types": "~2.1.24"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
"license": "MIT",
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
}
}
}

View File

@@ -21,6 +21,14 @@ if [ ! -d "node_modules" ]; then
npm install
fi
# Load environment variables from .env file if it exists
if [ -f .env ]; then
echo "📋 Loading environment from .env file..."
set -a # automatically export all variables created
source .env
set +a # stop auto-export
fi
# Detect local IP
if [[ "$OSTYPE" == "darwin"* ]]; then
# macOS
@@ -58,6 +66,13 @@ if kill -0 $PID 2>/dev/null; then
echo " API Key: dummy"
echo " Model: claude-local"
echo ""
if [ -n "$BRAVE_SEARCH_API_KEY" ]; then
echo "Brave Search: ✅ CONFIGURED"
else
echo "Brave Search: ⚠️ NOT SET (web search disabled)"
echo " To enable: Add BRAVE_SEARCH_API_KEY to .env file"
fi
echo ""
echo "Next Steps:"
echo " 1. Open your WordPress Admin"
echo " 2. Go to Agentic Writer → Settings → Local Backend"