- 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
308 lines
11 KiB
PHP
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>
|