Files
wp-agentic-writer/views/settings-backup/tab-local-backend.php
Dwindi Ramadhana d2c10756ab Add AI writing assistant plugin with local backend, brave search, and image generation support
- Implement local backend AI provider with Ollama integration
- Add Brave Search API integration for real-time search suggestions
- Add image generation manager with multiple AI providers
- Create hybrid provider system with local/cloud fallback
- Add comprehensive settings UI with provider management
- Implement Gutenberg sidebar with writing assistance controls
- Add SEO schema generation for AI-generated content
- Multiple provider support: OpenRouter, local backend, Codex
2026-05-17 10:48:05 +07:00

308 lines
11 KiB
PHP

<?php
/**
* Settings Tab: Local Backend
*
* @package WP_Agentic_Writer
* @var string $local_backend_url
* @var string $local_backend_key
* @var string $local_backend_model
* @var bool $local_backend_enabled
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
?>
<div class="row g-4">
<!-- Download Package -->
<div class="col-12">
<div class="card border-0 shadow-sm alert alert-info">
<div class="card-header bg-white border-bottom-0 pt-3">
<div class="d-flex align-items-center">
<div>
<h5 class="card-title mb-1 d-flex align-items-center gap-2">
<i class="bi bi-download text-primary"></i>
<?php esc_html_e( 'Step 1: Download Local Backend Package', 'wp-agentic-writer' ); ?>
</h5>
<p class="text-muted small mb-0">
<?php esc_html_e( 'Run AI inference on your own machine with your Claude CLI + Z.ai account', 'wp-agentic-writer' ); ?>
</p>
</div>
</div>
</div>
<div class="card-body">
<p class="mb-3">
<?php esc_html_e( 'Download the Local Backend proxy to run on your development machine. This allows unlimited, private AI content generation using your existing Claude CLI setup.', 'wp-agentic-writer' ); ?>
</p>
<a href="<?php echo esc_url( WP_AGENTIC_WRITER_URL . 'downloads/agentic-writer-local-backend.zip' ); ?>"
class="btn btn-primary btn-lg" download>
<i class="bi bi-download me-2"></i>
<?php esc_html_e( 'Download Local Backend v1.0.0', 'wp-agentic-writer' ); ?>
</a>
<details class="mt-3">
<summary class="fw-semibold" style="cursor: pointer;">
<?php esc_html_e( 'Prerequisites', 'wp-agentic-writer' ); ?>
</summary>
<ul class="mt-2">
<li>
✅ <strong><?php esc_html_e( 'Claude CLI', 'wp-agentic-writer' ); ?></strong> -
<?php esc_html_e( 'Get from', 'wp-agentic-writer' ); ?>
<a href="https://claude.ai/code" target="_blank">claude.ai/code</a>
<?php esc_html_e( 'or', 'wp-agentic-writer' ); ?>
<a href="https://z.ai" target="_blank">z.ai</a>
</li>
<li>
✅ <strong><?php esc_html_e( 'Node.js 18+', 'wp-agentic-writer' ); ?></strong> -
<a href="https://nodejs.org" target="_blank"><?php esc_html_e( 'Download', 'wp-agentic-writer' ); ?></a>
</li>
<li>
✅ <strong><?php esc_html_e( 'Z.ai Coding Plan or Anthropic API key', 'wp-agentic-writer' ); ?></strong> -
<?php esc_html_e( 'Configured in Claude CLI', 'wp-agentic-writer' ); ?>
</li>
</ul>
</details>
</div>
</div>
</div>
<!-- Configuration -->
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-header bg-white border-bottom-0 pt-3">
<div class="d-flex align-items-center">
<div>
<h5 class="card-title mb-1 d-flex align-items-center gap-2">
<i class="bi bi-gear-fill text-success"></i>
<?php esc_html_e( 'Step 2: Configure Connection', 'wp-agentic-writer' ); ?>
</h5>
<p class="text-muted small mb-0">
<?php esc_html_e( 'After starting the proxy, enter the connection details here', 'wp-agentic-writer' ); ?>
</p>
</div>
</div>
</div>
<div class="card-body">
<div class="mb-3">
<label for="local_backend_url" class="form-label fw-semibold">
<?php esc_html_e( 'Base URL', 'wp-agentic-writer' ); ?>
<span class="text-danger ms-2">*</span>
</label>
<input type="url"
class="form-control"
id="local_backend_url"
name="wp_agentic_writer_settings[local_backend_url]"
value="<?php echo esc_attr( $local_backend_url ); ?>"
placeholder="http://192.168.1.105:8080">
<div class="form-text">
<?php esc_html_e( 'Enter the URL from your Local Backend startup message (e.g., http://YOUR-IP:8080)', 'wp-agentic-writer' ); ?>
</div>
</div>
<div class="mb-3">
<label for="local_backend_key" class="form-label fw-semibold">
<?php esc_html_e( 'API Key', 'wp-agentic-writer' ); ?>
</label>
<input type="text"
class="form-control"
id="local_backend_key"
name="wp_agentic_writer_settings[local_backend_key]"
value="<?php echo esc_attr( $local_backend_key ); ?>"
placeholder="dummy">
<div class="form-text">
<?php esc_html_e( 'Use "dummy" for local backend (ignored by proxy)', 'wp-agentic-writer' ); ?>
</div>
</div>
<div class="mb-3">
<label for="local_backend_model" class="form-label fw-semibold">
<?php esc_html_e( 'Model', 'wp-agentic-writer' ); ?>
</label>
<input type="text"
class="form-control"
id="local_backend_model"
name="wp_agentic_writer_settings[local_backend_model]"
value="<?php echo esc_attr( $local_backend_model ); ?>"
placeholder="claude-local">
<div class="form-text">
<?php esc_html_e( 'Model identifier (informational only, proxy uses your Claude CLI default)', 'wp-agentic-writer' ); ?>
</div>
</div>
<div class="d-flex gap-2 align-items-center">
<button type="button" id="test-local-backend" class="btn btn-outline-primary">
<i class="bi bi-plug me-2"></i>
<?php esc_html_e( 'Test Connection', 'wp-agentic-writer' ); ?>
</button>
<span id="connection-status" class="ms-2"></span>
</div>
</div>
</div>
</div>
<!-- Task Routing (Optional) -->
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-header bg-white border-bottom-0 pt-3">
<div class="d-flex align-items-center">
<div>
<h5 class="card-title mb-1 d-flex align-items-center gap-2">
<i class="bi bi-diagram-3 text-warning"></i>
<?php esc_html_e( 'Step 3: Provider Routing (Advanced)', 'wp-agentic-writer' ); ?>
</h5>
<p class="text-muted small mb-0">
<?php esc_html_e( 'Choose which provider to use for each task type', 'wp-agentic-writer' ); ?>
</p>
</div>
</div>
</div>
<div class="card-body">
<div class="alert alert-info mb-3">
<i class="bi bi-info-circle me-2"></i>
<strong><?php esc_html_e( 'Recommended Setup:', 'wp-agentic-writer' ); ?></strong>
<?php esc_html_e( 'Use Local Backend for all text tasks (free, fast, private). Use OpenRouter for images (only option).', 'wp-agentic-writer' ); ?>
</div>
<?php
$task_types = array(
'chat' => __( 'Chat & Discussion', 'wp-agentic-writer' ),
'clarity' => __( 'Clarity Check & Quiz', 'wp-agentic-writer' ),
'planning' => __( 'Outline Planning', 'wp-agentic-writer' ),
'writing' => __( 'Article Writing', 'wp-agentic-writer' ),
'refinement' => __( 'Content Refinement', 'wp-agentic-writer' ),
'image' => __( 'Image Generation', 'wp-agentic-writer' ),
);
$task_providers = $settings['task_providers'] ?? array();
?>
<table class="table">
<thead>
<tr>
<th><?php esc_html_e( 'Task Type', 'wp-agentic-writer' ); ?></th>
<th><?php esc_html_e( 'Provider', 'wp-agentic-writer' ); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ( $task_types as $task_key => $task_label ) : ?>
<tr>
<td><?php echo esc_html( $task_label ); ?></td>
<td>
<select class="form-select form-select-sm"
name="wp_agentic_writer_settings[task_providers][<?php echo esc_attr( $task_key ); ?>]">
<?php
$current_provider = $task_providers[ $task_key ] ?? 'openrouter';
// Available providers per task
$providers = array(
'openrouter' => '☁️ OpenRouter (Cloud)',
);
// Add local backend for text tasks
if ( 'image' !== $task_key ) {
$providers['local_backend'] = '🏠 Local Backend (Free)';
$providers['codex'] = '🔗 Codex (OpenAI)';
}
foreach ( $providers as $provider_key => $provider_label ) :
?>
<option value="<?php echo esc_attr( $provider_key ); ?>"
<?php selected( $current_provider, $provider_key ); ?>>
<?php echo esc_html( $provider_label ); ?>
</option>
<?php endforeach; ?>
</select>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<!-- Help -->
<div class="col-12">
<div class="card border-0 shadow-sm border-warning">
<div class="card-header bg-white border-bottom-0 pt-3">
<h5 class="card-title mb-0 d-flex align-items-center gap-2">
<i class="bi bi-question-circle text-warning"></i>
<?php esc_html_e( 'Troubleshooting', 'wp-agentic-writer' ); ?>
</h5>
</div>
<div class="card-body">
<ul class="mb-0">
<li>
<strong><?php esc_html_e( 'Connection failed?', 'wp-agentic-writer' ); ?></strong>
<?php esc_html_e( 'Ensure proxy is running:', 'wp-agentic-writer' ); ?>
<code>./start-proxy.sh</code>
</li>
<li>
<strong><?php esc_html_e( 'Wrong IP?', 'wp-agentic-writer' ); ?></strong>
<?php esc_html_e( 'Run', 'wp-agentic-writer' ); ?>
<code>./get-local-ip.sh</code>
<?php esc_html_e( 'to find correct address', 'wp-agentic-writer' ); ?>
</li>
<li>
<strong><?php esc_html_e( 'Firewall blocking?', 'wp-agentic-writer' ); ?></strong>
<?php esc_html_e( 'Allow Node.js on port 8080 in your system firewall', 'wp-agentic-writer' ); ?>
</li>
<li>
<strong><?php esc_html_e( 'Claude not found?', 'wp-agentic-writer' ); ?></strong>
<?php esc_html_e( 'Check Claude CLI:', 'wp-agentic-writer' ); ?>
<code>which claude</code>
<?php esc_html_e( 'or', 'wp-agentic-writer' ); ?>
<code>claude --version</code>
</li>
</ul>
<p class="mt-3 mb-0">
<strong><?php esc_html_e( 'Need help?', 'wp-agentic-writer' ); ?></strong>
<?php esc_html_e( 'Check the README.md and TROUBLESHOOTING.md files in the downloaded package.', 'wp-agentic-writer' ); ?>
</p>
</div>
</div>
</div>
</div>
<script>
jQuery(document).ready(function($) {
$('#test-local-backend').on('click', function() {
const btn = $(this);
const status = $('#connection-status');
const url = $('#local_backend_url').val();
if (!url) {
status.html('<span class="text-warning">⚠️ Enter Base URL first</span>');
return;
}
btn.prop('disabled', true).html('<i class="spinner-border spinner-border-sm me-2"></i>Testing...');
status.html('<span class="text-white" style="color:#17a2b8 !important;">⏳ Connecting...</span>');
$.ajax({
url: ajaxurl,
method: 'POST',
data: {
action: 'wpaw_test_local_backend',
url: url,
nonce: '<?php echo esc_js( wp_create_nonce( 'wpaw_test_local_backend' ) ); ?>'
},
success: function(response) {
if (response.success) {
status.html('<span class="text-success">✅ ' + response.data.message + '</span>');
} else {
status.html('<span class="text-danger">❌ ' + (response.data.message || 'Failed') + '</span>');
}
},
error: function(xhr) {
status.html('<span class="text-danger">❌ Connection failed. Check URL and proxy status.</span>');
},
complete: function() {
btn.prop('disabled', false).html('<i class="bi bi-plug me-2"></i><?php esc_html_e( 'Test Connection', 'wp-agentic-writer' ); ?>');
}
});
});
});
</script>