refactor: Cleanup git state - commit all staged changes

Major refactoring cleanup:
- Add new controller architecture (class-controller-*.php)
- Add new settings-v2 UI (views/settings-v2/)
- Add new CSS architecture (agentic-sidebar.css, tokens)
- Add esbuild build pipeline (scripts/build.js, package.json)
- Add composer dependencies (vendor/)
- Add frontend src directory (assets/js/src/index.jsx)
- Add documentation files
- Remove old/obsolete files (class-settings.php, old CSS)

This commits all pending changes from previous refactoring efforts.
This commit is contained in:
Dwindi Ramadhana
2026-06-17 05:27:58 +07:00
parent d3f142222c
commit 690991c526
7963 changed files with 941566 additions and 67372 deletions

View File

@@ -0,0 +1,194 @@
<?php
/**
* Settings V2 layout — Stitch rebuild.
*
* @package WP_Agentic_Writer
* @var array $view_data Prepared view data from class-settings-v2.php.
*/
if (!defined("ABSPATH")) {
exit();
}
// phpcs:ignore WordPress.PHP.DontExtract.extract_extract -- View templates are intentionally passed prepared variables.
extract($view_data);
$api_connected = !empty($api_key);
$models_ready = !empty($planning_model) && !empty($writing_model);
$budget_percent_safe = min(100, (float) $budget_percent);
$user_agent = isset($_SERVER["HTTP_USER_AGENT"])
? sanitize_text_field(wp_unslash($_SERVER["HTTP_USER_AGENT"]))
: "";
$cmd_key = false !== strpos($user_agent, "Mac OS") ? "" : "Ctrl";
$settings_tabs = [
"general" => ["General", "6"],
"models" => ["OpenRouter", "6"],
"local-backend" => ["Custom Router", "3"],
"tools" => ["Tools", "1"],
"memanto" => ["MEMANTO", "3"],
"cost-log" => ["Cost Log", "2"],
"guide" => ["Model Guide", "3"],
];
?>
<div class="wrap wpaw2-settings">
<script>
// Intercept WP "Settings saved" admin notice → use our Agentic toast
document.addEventListener('DOMContentLoaded', function() {
var wpNotice = document.querySelector('#setting-error-settings_updated, .notice.settings-error');
if (wpNotice) {
var msg = wpNotice.querySelector('p');
var text = msg ? msg.textContent.replace('Settings saved.', 'Settings saved').trim() : 'Settings saved';
wpNotice.style.display = 'none';
// Delegate to existing toast system
var toast = document.getElementById('wpaw2-toast');
var body = document.getElementById('wpaw2-toast-message');
if (toast && body) {
body.textContent = text;
toast.className = 'toast show toast-success';
clearTimeout(toast._timer);
toast._timer = setTimeout(function() { toast.classList.remove('show'); }, 2600);
}
}
});
</script>
<div class="main">
<header class="admin-top">
<div class="crumb"><?php esc_html_e(
"Agentic Writer",
"wp-agentic-writer",
); ?> / <strong id="wpaw2-crumb-tab"><?php esc_html_e(
"General",
"wp-agentic-writer",
); ?></strong></div>
<div class="top-actions">
<button type="button" class="btn btn-small" data-aw2-tab="guide"><?php esc_html_e(
"Open Guide",
"wp-agentic-writer",
); ?></button>
<button type="button" class="btn btn-small btn-danger" id="wpaw-reset-settings"><?php esc_html_e(
"Reset Defaults",
"wp-agentic-writer",
); ?></button>
<button type="submit" form="wpaw2-settings-form" class="btn btn-primary btn-small"><?php esc_html_e(
"Save Settings",
"wp-agentic-writer",
); ?></button>
</div>
</header>
<main class="page">
<section class="hero">
<div class="hero-card">
<p class="eyebrow"><?php esc_html_e(
"Control center",
"wp-agentic-writer",
); ?></p>
<h1><?php esc_html_e(
"Configure your agentic writing workflow.",
"wp-agentic-writer",
); ?></h1>
<p class="hero-copy"><?php esc_html_e(
"Manage providers, model routing, memory, cost controls, and custom endpoint integrations from one lightweight settings interface.",
"wp-agentic-writer",
); ?></p>
</div>
<div class="status-panel">
<div class="workflow-step"><span class="step-dot">1</span><span class="step-label"><?php esc_html_e(
"OpenRouter",
"wp-agentic-writer",
); ?></span><span class="status <?php echo esc_attr(
$api_connected ? "connected" : "warn",
); ?>"><?php echo $api_connected
? esc_html__("Connected", "wp-agentic-writer")
: esc_html__("Missing key", "wp-agentic-writer"); ?></span></div>
<div class="workflow-step"><span class="step-dot">2</span><span class="step-label"><?php esc_html_e(
"Models",
"wp-agentic-writer",
); ?></span><span class="status <?php echo esc_attr(
$models_ready ? "connected" : "warn",
); ?>"><?php echo $models_ready
? esc_html__("Ready", "wp-agentic-writer")
: esc_html__("Review", "wp-agentic-writer"); ?></span></div>
<div class="workflow-step"><span class="step-dot">3</span><span class="step-label"><?php esc_html_e(
"Budget",
"wp-agentic-writer",
); ?></span><span class="status <?php echo esc_attr(
"danger" === $budget_status
? "error"
: ("warning" === $budget_status
? "warn"
: "connected"),
); ?>"><?php echo esc_html(
number_format_i18n($budget_percent_safe, 1),
); ?>%</span></div>
</div>
</section>
<form method="post" action="options.php" id="wpaw2-settings-form">
<?php settings_fields("wp_agentic_writer_settings"); ?>
<section class="tabs-wrap">
<aside class="tab-sidebar" aria-label="Settings sections">
<div class="tab-group">
<div class="tab-group-title"><?php esc_html_e(
"Setup",
"wp-agentic-writer",
); ?></div>
<?php foreach (
["general", "models", "local-backend", "tools", "memanto"]
as $tab_key
): ?>
<button type="button" class="tab-btn" data-aw2-tab="<?php echo esc_attr(
$tab_key,
); ?>" data-label="<?php echo esc_attr(
$settings_tabs[$tab_key][0],
); ?>" aria-selected="<?php echo "general" === $tab_key
? "true"
: "false"; ?>"><span><?php echo esc_html(
$settings_tabs[$tab_key][0],
); ?></span><span class="tab-count"><?php echo esc_html(
$settings_tabs[$tab_key][1],
); ?></span></button>
<?php endforeach; ?>
</div>
<div class="tab-group">
<div class="tab-group-title"><?php esc_html_e(
"Reference",
"wp-agentic-writer",
); ?></div>
<?php foreach (["cost-log", "guide"] as $tab_key): ?>
<button type="button" class="tab-btn" data-aw2-tab="<?php echo esc_attr(
$tab_key,
); ?>" data-label="<?php echo esc_attr(
$settings_tabs[$tab_key][0],
); ?>" aria-selected="false"><span><?php echo esc_html(
$settings_tabs[$tab_key][0],
); ?></span><span class="tab-count"><?php echo esc_html(
$settings_tabs[$tab_key][1],
); ?></span></button>
<?php endforeach; ?>
</div>
</aside>
<div>
<section class="tab-panel active" id="general"><?php require WP_AGENTIC_WRITER_DIR .
"views/settings-v2/tab-general.php"; ?></section>
<section class="tab-panel" id="models"><?php require WP_AGENTIC_WRITER_DIR .
"views/settings-v2/tab-models.php"; ?></section>
<section class="tab-panel" id="local-backend"><?php require WP_AGENTIC_WRITER_DIR .
"views/settings-v2/tab-local-backend.php"; ?></section>
<section class="tab-panel" id="tools"><?php require WP_AGENTIC_WRITER_DIR .
"views/settings-v2/tab-tools.php"; ?></section>
<section class="tab-panel" id="memanto"><?php require WP_AGENTIC_WRITER_DIR .
"views/settings-v2/tab-memanto.php"; ?></section>
<section class="tab-panel" id="cost-log"><?php require WP_AGENTIC_WRITER_DIR .
"views/settings-v2/tab-cost-log.php"; ?></section>
<section class="tab-panel" id="guide"><?php require WP_AGENTIC_WRITER_DIR .
"views/settings-v2/tab-guide.php"; ?></section>
</div>
</section>
</form>
</main>
</div>
<div class="toast" id="wpaw2-toast" role="status" aria-live="polite"><button type="button" class="btn btn-small" id="wpaw2-toast-close" style="float:right">×</button><span id="wpaw2-toast-message"></span></div>
</div>

1332
views/settings-v2/style.css Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,66 @@
<?php
/**
* Settings V2: Cost Log.
*
* @package WP_Agentic_Writer
*/
if (!defined("ABSPATH")) {
exit();
} ?>
<div class="section-head"><div><p class="eyebrow"><?php esc_html_e(
"Spend visibility",
"wp-agentic-writer",
); ?></p><h2><?php esc_html_e(
"OpenRouter cost log",
"wp-agentic-writer",
); ?></h2><p><?php esc_html_e(
"Review usage, monthly spend, and per-post OpenRouter costs.",
"wp-agentic-writer",
); ?></p></div><button type="button" class="btn btn-small" id="wpaw-export-csv"><?php esc_html_e(
"Export CSV",
"wp-agentic-writer",
); ?></button></div>
<div class="panel"><div class="panel-head"><div class="panel-title"><h3><?php esc_html_e(
"Monthly summary",
"wp-agentic-writer",
); ?></h3><p><?php esc_html_e(
"Current month usage from the cost tracker.",
"wp-agentic-writer",
); ?></p></div></div><div class="panel-body grid-3"><div class="metric-card"><div class="metric-value">$<?php echo esc_html(
number_format_i18n($monthly_used, 2),
); ?></div><div class="metric-label"><?php esc_html_e(
"Used",
"wp-agentic-writer",
); ?></div></div><div class="metric-card"><div class="metric-value">$<?php echo esc_html(
number_format_i18n($monthly_budget, 2),
); ?></div><div class="metric-label"><?php esc_html_e(
"Budget",
"wp-agentic-writer",
); ?></div></div><div class="metric-card"><div class="metric-value"><?php echo esc_html(
number_format_i18n($budget_percent, 1),
); ?>%</div><div class="progress"><span style="width: <?php echo esc_attr(
min(100, $budget_percent),
); ?>%"></span></div><div class="metric-label"><?php esc_html_e(
"Budget usage",
"wp-agentic-writer",
); ?></div></div></div></div>
<div class="panel"><div class="panel-head"><div class="panel-title"><h3><?php esc_html_e(
"Recent usage",
"wp-agentic-writer",
); ?></h3><p><?php esc_html_e(
"Expand each post to see action-level calls and costs.",
"wp-agentic-writer",
); ?></p></div></div><div class="panel-body"><table class="ds-table" id="wpaw-cost-log-table"><thead><tr><th><?php esc_html_e(
"Post",
"wp-agentic-writer",
); ?></th><th><?php esc_html_e(
"Actions / calls",
"wp-agentic-writer",
); ?></th><th><?php esc_html_e(
"Total cost",
"wp-agentic-writer",
); ?></th></tr></thead><tbody id="wpaw-cost-log-tbody"><tr><td colspan="3"><?php esc_html_e(
"Cost data will appear after OpenRouter generations.",
"wp-agentic-writer",
); ?></td></tr></tbody></table></div></div>

View File

@@ -0,0 +1,123 @@
<?php
/**
* Settings V2: General.
*
* @package WP_Agentic_Writer
*/
if (!defined("ABSPATH")) {
exit();
} ?>
<div class="section-head">
<div>
<p class="eyebrow"><?php esc_html_e("Foundation", "wp-agentic-writer"); ?></p>
<h2><?php esc_html_e("General settings", "wp-agentic-writer"); ?></h2>
<p><?php esc_html_e(
"Manage your agent's core identity, clarification limits, and language preferences.",
"wp-agentic-writer",
); ?></p>
</div>
</div>
<div class="panel">
<div class="panel-head">
<div class="panel-title">
<h3><?php esc_html_e(
"Global Context & Brand Voice",
"wp-agentic-writer",
); ?></h3>
<p><?php esc_html_e(
"Set unbreakable rules, tone, and identity for the AI. This context is injected into every single agentic request.",
"wp-agentic-writer",
); ?></p>
</div>
</div>
<div class="panel-body">
<div class="field" style="width: 100%;">
<textarea class="field-control" id="global_context" name="wp_agentic_writer_settings[global_context]" rows="5" placeholder="<?php esc_attr_e(
"e.g., You are a senior attorney writing for a legal blog. Never give direct legal advice. Always use British English. Avoid mentioning competitors.",
"wp-agentic-writer",
); ?>" style="width: 100%; font-family: ui-monospace, SFMono-Regular, monospace; resize: vertical;"><?php echo esc_textarea(
$global_context ?? "",
); ?></textarea>
<p class="help" style="margin-top: 8px;">
<?php esc_html_e(
"Think of this as the DNA of your agent. While Memanto learns from user feedback organically, this field defines hard guardrails that the AI must always follow.",
"wp-agentic-writer",
); ?>
</p>
</div>
</div>
</div>
<div class="panel">
<div class="panel-head"><div class="panel-title"><h3><?php esc_html_e(
"Research & clarification",
"wp-agentic-writer",
); ?></h3><p><?php esc_html_e(
"Control question generation.",
"wp-agentic-writer",
); ?></p></div></div>
<div class="panel-body">
<label class="switch-row" style="margin-top:0px"><input type="checkbox" name="wp_agentic_writer_settings[enable_clarification_quiz]" value="1" <?php checked(
$enable_clarification_quiz,
); ?>><span class="switch"></span><span><?php esc_html_e(
"Ask clarification quiz before writing",
"wp-agentic-writer",
); ?></span></label>
</div>
</div>
<div class="panel">
<div class="panel-head"><div class="panel-title"><h3><?php esc_html_e(
"Language preferences",
"wp-agentic-writer",
); ?></h3><p><?php esc_html_e(
"Preferred writing languages and chat memory limits.",
"wp-agentic-writer",
); ?></p></div></div>
<div class="panel-body grid-2">
<div class="field"><label for="chat_history_limit"><?php esc_html_e(
"Chat history limit",
"wp-agentic-writer",
); ?></label><input class="field-control" type="number" min="1" id="chat_history_limit" name="wp_agentic_writer_settings[chat_history_limit]" value="<?php echo esc_attr(
$chat_history_limit,
); ?>"></div>
<div class="field"><label for="clarity_confidence_threshold"><?php esc_html_e(
"Clarity threshold",
"wp-agentic-writer",
); ?></label><select class="field-control" id="clarity_confidence_threshold" name="wp_agentic_writer_settings[clarity_confidence_threshold]"><option value="0.4" <?php selected(
$clarity_confidence_threshold,
"0.4",
); ?>>Relaxed</option><option value="0.6" <?php selected(
$clarity_confidence_threshold,
"0.6",
); ?>>Balanced</option><option value="0.8" <?php selected(
$clarity_confidence_threshold,
"0.8",
); ?>>Strict</option></select></div>
<div class="field language-field"><label for="preferred_languages"><?php esc_html_e(
"Preferred languages",
"wp-agentic-writer",
); ?></label><select class="field-control" id="preferred_languages" name="wp_agentic_writer_settings[preferred_languages][]" multiple><?php foreach (
(array) $available_languages
as $language_value => $language_label
): ?><option value="<?php echo esc_attr($language_value); ?>" <?php selected(
in_array($language_value, (array) $preferred_languages, true),
); ?>><?php echo esc_html(
$language_label,
); ?></option><?php endforeach; ?></select><p class="help"><?php esc_html_e(
"These are passed to the editor language controls.",
"wp-agentic-writer",
); ?></p></div>
<div class="field"><label for="custom_languages"><?php esc_html_e(
"Custom languages",
"wp-agentic-writer",
); ?></label><input class="field-control" type="text" id="custom_languages" name="wp_agentic_writer_settings[custom_languages][]" value="<?php echo esc_attr(
implode(", ", (array) $custom_languages),
); ?>" placeholder="Javanese, Sundanese"><p class="help"><?php esc_html_e(
"Separate multiple custom languages with commas.",
"wp-agentic-writer",
); ?></p></div>
</div>
</div>

View File

@@ -0,0 +1,246 @@
<?php
/**
* Settings V2: Guide.
*
* @package WP_Agentic_Writer
*/
if (!defined("ABSPATH")) {
exit();
} ?>
<div class="section-head"><div><p class="eyebrow"><?php esc_html_e(
"Reference",
"wp-agentic-writer",
); ?></p><h2><?php esc_html_e(
"Model guide",
"wp-agentic-writer",
); ?></h2><p><?php esc_html_e(
"Understand which model role is used for each feature and estimate costs.",
"wp-agentic-writer",
); ?></p></div></div>
<div class="panel">
<div class="panel-head"><div class="panel-title"><h3><?php esc_html_e(
"Tasks and model roles",
"wp-agentic-writer",
); ?></h3><p><?php esc_html_e(
"Each workflow stage uses a dedicated model.",
"wp-agentic-writer",
); ?></p></div></div>
<div class="panel-body">
<table class="ds-table">
<thead><tr>
<th><?php esc_html_e("Task", "wp-agentic-writer"); ?></th>
<th><?php esc_html_e("Model role", "wp-agentic-writer"); ?></th>
<th><?php esc_html_e("Est. cost", "wp-agentic-writer"); ?></th>
<th><?php esc_html_e("Purpose", "wp-agentic-writer"); ?></th>
</tr></thead>
<tbody>
<tr>
<td><strong><?php esc_html_e("Planning", "wp-agentic-writer"); ?></strong></td>
<td><span class="chip on"><?php esc_html_e(
"Planning",
"wp-agentic-writer",
); ?></span></td>
<td class="guide-cost">~$0.001</td>
<td><?php esc_html_e(
"Creates article outline with sections and structure.",
"wp-agentic-writer",
); ?></td>
</tr>
<tr>
<td><strong><?php esc_html_e(
"Clarity Check",
"wp-agentic-writer",
); ?></strong></td>
<td><span class="chip on"><?php esc_html_e(
"Clarity",
"wp-agentic-writer",
); ?></span></td>
<td class="guide-cost">~$0.0005</td>
<td><?php esc_html_e(
"Analyzes your prompt and asks clarifying questions.",
"wp-agentic-writer",
); ?></td>
</tr>
<tr class="ds-table-highlight">
<td><strong><?php esc_html_e("Writing", "wp-agentic-writer"); ?></strong></td>
<td><span class="chip on"><?php esc_html_e(
"Writing",
"wp-agentic-writer",
); ?></span></td>
<td class="guide-cost">~$0.050.15</td>
<td><?php esc_html_e(
"Generates full article content section by section.",
"wp-agentic-writer",
); ?></td>
</tr>
<tr>
<td><strong><?php esc_html_e("Chat", "wp-agentic-writer"); ?></strong></td>
<td><span class="chip on"><?php esc_html_e(
"Chat",
"wp-agentic-writer",
); ?></span></td>
<td class="guide-cost">~$0.001</td>
<td><?php esc_html_e(
"Answers questions and provides quick assistance.",
"wp-agentic-writer",
); ?></td>
</tr>
<tr>
<td><strong><?php esc_html_e(
"Block Refinement",
"wp-agentic-writer",
); ?></strong></td>
<td><span class="chip on"><?php esc_html_e(
"Refinement",
"wp-agentic-writer",
); ?></span></td>
<td class="guide-cost">~$0.010.03</td>
<td><?php esc_html_e(
"Improves or rewrites selected content blocks.",
"wp-agentic-writer",
); ?></td>
</tr>
<tr>
<td><strong><?php esc_html_e(
"Image Generation",
"wp-agentic-writer",
); ?></strong></td>
<td><span class="chip on"><?php esc_html_e(
"Image",
"wp-agentic-writer",
); ?></span></td>
<td class="guide-cost">~$0.0030.04</td>
<td><?php esc_html_e(
"Creates images for articles.",
"wp-agentic-writer",
); ?></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="panel">
<div class="panel-head"><div class="panel-title"><h3><?php esc_html_e(
"Recommended models",
"wp-agentic-writer",
); ?></h3><p><?php esc_html_e(
"Best models for each purpose based on quality and cost.",
"wp-agentic-writer",
); ?></p></div></div>
<div class="panel-body">
<table class="ds-table">
<thead><tr>
<th><?php esc_html_e("Model", "wp-agentic-writer"); ?></th>
<th><?php esc_html_e("Best for", "wp-agentic-writer"); ?></th>
<th><?php esc_html_e("Cost / 1M tokens", "wp-agentic-writer"); ?></th>
<th><?php esc_html_e("Notes", "wp-agentic-writer"); ?></th>
</tr></thead>
<tbody>
<tr>
<td><strong>Gemini 2.5 Flash</strong></td>
<td><?php esc_html_e("Chat, Clarity, Planning", "wp-agentic-writer"); ?></td>
<td class="guide-cost">$0.15 / $0.60</td>
<td>⭐ <?php esc_html_e(
"Best balanced option. Fast reasoning.",
"wp-agentic-writer",
); ?></td>
</tr>
<tr>
<td><strong>Claude 3.5 Sonnet</strong></td>
<td><?php esc_html_e("Writing, Refinement", "wp-agentic-writer"); ?></td>
<td class="guide-cost">$3.00 / $15.00</td>
<td>⭐ <?php esc_html_e(
"Best quality writing. Recommended.",
"wp-agentic-writer",
); ?></td>
</tr>
<tr>
<td><strong>GPT-4.1</strong></td>
<td><?php esc_html_e(
"Writing, Refinement (Premium)",
"wp-agentic-writer",
); ?></td>
<td class="guide-cost">$2.00 / $8.00</td>
<td>🏆 <?php esc_html_e(
"Premium option. Excellent instruction following.",
"wp-agentic-writer",
); ?></td>
</tr>
<tr>
<td><strong>GPT-4o</strong></td>
<td><?php esc_html_e("Image Generation", "wp-agentic-writer"); ?></td>
<td class="guide-cost">$2.50 / $10.00</td>
<td>⭐ <?php esc_html_e(
"Generates article images from text prompts.",
"wp-agentic-writer",
); ?></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="panel">
<div class="panel-head"><div class="panel-title"><h3><?php esc_html_e(
"Cost examples",
"wp-agentic-writer",
); ?></h3><p><?php esc_html_e(
"Real-world cost estimates for common tasks.",
"wp-agentic-writer",
); ?></p></div></div>
<div class="panel-body">
<div class="grid-3">
<div class="metric-card guide-cost-card">
<h3><?php esc_html_e("Single article (Balanced)", "wp-agentic-writer"); ?></h3>
<ul class="guide-cost-list">
<li><?php esc_html_e("Clarity Check", "wp-agentic-writer"); ?>: ~$0.001</li>
<li><?php esc_html_e("Planning", "wp-agentic-writer"); ?>: ~$0.001</li>
<li><?php esc_html_e(
"Writing (5 sections)",
"wp-agentic-writer",
); ?>: ~$0.10</li>
<li><?php esc_html_e("1 Image", "wp-agentic-writer"); ?>: ~$0.003</li>
</ul>
<div class="guide-cost-total">
<span><?php esc_html_e("Total", "wp-agentic-writer"); ?></span>
<strong>~$0.100.15</strong>
</div>
</div>
<div class="metric-card guide-cost-card">
<h3><?php esc_html_e("10 articles / month", "wp-agentic-writer"); ?></h3>
<ul class="guide-cost-list">
<li><?php esc_html_e('10 articles × $0.15', "wp-agentic-writer"); ?></li>
<li><?php esc_html_e(
"Some chat interactions",
"wp-agentic-writer",
); ?>: ~$0.05</li>
<li><?php esc_html_e("Refinements", "wp-agentic-writer"); ?>: ~$0.20</li>
</ul>
<div class="guide-cost-total">
<span><?php esc_html_e("Total", "wp-agentic-writer"); ?></span>
<strong>~$1.502.00</strong>
</div>
</div>
<div class="metric-card guide-cost-card">
<h3><?php esc_html_e("With web search", "wp-agentic-writer"); ?></h3>
<ul class="guide-cost-list">
<li><?php esc_html_e(
'Add ~$0.02 per search request',
"wp-agentic-writer",
); ?></li>
<li><?php esc_html_e(
"Typical: 12 searches per article",
"wp-agentic-writer",
); ?></li>
</ul>
<div class="guide-cost-total">
<span><?php esc_html_e("Extra", "wp-agentic-writer"); ?></span>
<strong class="guide-cost-warn">~$0.020.04</strong>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,298 @@
<?php
/**
* Settings V2: Custom Endpoint.
*
* @package WP_Agentic_Writer
*/
if (!defined("ABSPATH")) {
exit();
} ?>
<div class="section-head">
<div>
<p class="eyebrow"><?php esc_html_e(
"Custom API Router",
"wp-agentic-writer",
); ?></p>
<h2><?php esc_html_e("Custom Router", "wp-agentic-writer"); ?></h2>
<p><?php esc_html_e(
"Connect any OpenAI-compatible API — Ollama, LM Studio, llama.cpp, vLLM, or your own proxy.",
"wp-agentic-writer",
); ?></p>
</div>
<span class="status <?php echo !empty($local_backend_url)
? "connected"
: "warn"; ?>">
<?php echo !empty($local_backend_url)
? esc_html__("Configured", "wp-agentic-writer")
: esc_html__("Optional", "wp-agentic-writer"); ?>
</span>
</div>
<div class="subtab-nav" role="tablist">
<button type="button" class="subtab-btn" role="tab" aria-selected="true" data-aw2-subtab-target="cr-connection">Connection</button>
<button type="button" class="subtab-btn" role="tab" aria-selected="false" data-aw2-subtab-target="cr-models">Models</button>
</div>
<!-- =======================
TAB: CONNECTION
======================= -->
<div class="subtab-panel active" id="cr-connection">
<!-- Connection panel -->
<div class="panel">
<div class="panel-head">
<div class="panel-title">
<h3><?php esc_html_e("Connection", "wp-agentic-writer"); ?></h3>
<p><?php esc_html_e(
"Enter the base URL and API key for your OpenAI-compatible endpoint.",
"wp-agentic-writer",
); ?></p>
</div>
<button type="button" class="btn btn-small" id="wpaw-test-local-backend">
<?php esc_html_e("Test connection", "wp-agentic-writer"); ?>
</button>
</div>
<div class="panel-body grid-2">
<div class="field">
<label><?php esc_html_e("Base URL", "wp-agentic-writer"); ?></label>
<input class="field-control" type="url" id="local_backend_url"
name="wp_agentic_writer_settings[local_backend_url]"
value="<?php echo esc_attr($local_backend_url); ?>"
placeholder="https://api.example.com">
</div>
<div class="field">
<label><?php esc_html_e("API Key", "wp-agentic-writer"); ?></label>
<input class="field-control" type="text" id="local_backend_key"
name="wp_agentic_writer_settings[local_backend_key]"
value="<?php echo esc_attr($local_backend_key); ?>"
placeholder="sk-...">
</div>
</div>
</div>
<!-- Image Connection panel -->
<div class="panel">
<div class="panel-head">
<div class="panel-title">
<h3><?php esc_html_e(
"Image Generation Connection",
"wp-agentic-writer",
); ?></h3>
<p><?php esc_html_e(
"When enabled, image generation tasks will be sent to this endpoint. If disabled, images will be safely generated via OpenRouter.",
"wp-agentic-writer",
); ?></p>
</div>
<div style="display: flex; gap: 10px; align-items: center;">
<button type="button" class="btn btn-small" id="wpaw-test-local-image" style="white-space: nowrap; <?php echo empty(
$local_backend_image_enabled
)
? "display:none;"
: ""; ?>">
<?php esc_html_e("Test connection", "wp-agentic-writer"); ?>
</button>
<label class="switch-row" style="margin:0">
<input type="checkbox" id="wpaw-ce-image-enabled"
name="wp_agentic_writer_settings[local_backend_image_enabled]"
value="1" <?php checked(!empty($local_backend_image_enabled)); ?>>
<span class="switch"></span>
</label>
</div>
</div>
<div class="panel-body grid-2" id="wpaw-ce-image-panel" <?php echo empty(
$local_backend_image_enabled
)
? "hidden"
: ""; ?>>
<div class="field">
<label><?php esc_html_e(
"Image Base URL (Optional)",
"wp-agentic-writer",
); ?></label>
<input class="field-control" type="url" id="local_backend_image_url"
name="wp_agentic_writer_settings[local_backend_image_url]"
value="<?php echo esc_attr($local_backend_image_url); ?>"
placeholder="https://api.images.example.com">
</div>
<div class="field">
<label><?php esc_html_e(
"Image API Key (Optional)",
"wp-agentic-writer",
); ?></label>
<input class="field-control" type="text" id="local_backend_image_key"
name="wp_agentic_writer_settings[local_backend_image_key]"
value="<?php echo esc_attr($local_backend_image_key); ?>"
placeholder="sk-...">
</div>
</div>
</div>
<!-- Hidden legacy field — keeps backward compat; value auto-synced by JS from per-task models -->
<input type="hidden" id="local_backend_model"
name="wp_agentic_writer_settings[local_backend_model]"
value="<?php echo esc_attr($local_backend_model); ?>">
</div>
<!-- =======================
TAB: TOOLS
======================= -->
<div class="subtab-panel" id="cr-tools">
<!-- Brave Search Panel for Local Backend -->
<div class="panel">
<div class="panel-head">
<div class="panel-title">
<h3><?php esc_html_e(
"Brave Search (Web Research)",
"wp-agentic-writer",
); ?></h3>
<p><?php esc_html_e(
"Local endpoints cannot search the web natively. Provide a Brave Search API key (free tier allows 2,000 req/mo) so WordPress can fetch web context before prompting your model.",
"wp-agentic-writer",
); ?></p>
</div>
</div>
<div class="panel-body grid-2">
<div class="field">
<label for="brave_search_api_key"><?php esc_html_e(
"Brave Search API key",
"wp-agentic-writer",
); ?></label>
<div class="password-row">
<input class="field-control" type="password" id="brave_search_api_key" name="wp_agentic_writer_settings[brave_search_api_key]" value="<?php echo esc_attr(
$brave_search_api_key,
); ?>">
<button type="button" class="btn" data-aw2-toggle-password="#brave_search_api_key"><?php esc_html_e(
"Show",
"wp-agentic-writer",
); ?></button>
</div>
</div>
<div class="field">
<label for="search_depth"><?php esc_html_e(
"Search depth",
"wp-agentic-writer",
); ?></label>
<select class="field-control" id="search_depth" name="wp_agentic_writer_settings[search_depth]">
<option value="light" <?php selected($search_depth, "light"); ?>>Light</option>
<option value="medium" <?php selected(
$search_depth,
"medium",
); ?>>Medium</option>
<option value="deep" <?php selected($search_depth, "deep"); ?>>Deep</option>
</select>
</div>
</div>
</div>
</div>
<!-- =======================
TAB: MODELS
======================= -->
<div class="subtab-panel" id="cr-models">
<!-- Enable toggle + Task routing panel -->
<div class="panel">
<div class="panel-head">
<div class="panel-title">
<h3><?php esc_html_e("Task routing", "wp-agentic-writer"); ?></h3>
<p><?php esc_html_e(
"Activate Custom Router, then assign a model code per task.",
"wp-agentic-writer",
); ?></p>
</div>
<label class="switch-row" style="margin:0">
<input type="checkbox" id="wpaw-ce-enabled"
name="wp_agentic_writer_settings[local_backend_enabled]"
value="1" <?php checked($local_backend_enabled); ?>>
<span class="switch"></span>
</label>
</div>
<div class="panel-body" id="wpaw-ce-routing" <?php echo $local_backend_enabled
? ""
: "hidden"; ?>>
<table class="ds-table">
<thead>
<tr>
<th><?php esc_html_e("Task", "wp-agentic-writer"); ?></th>
<th><?php esc_html_e("Model Code", "wp-agentic-writer"); ?></th>
</tr>
</thead>
<tbody>
<?php foreach (
["chat", "clarity", "planning", "writing", "refinement", "image"]
as $task_key
):
$task_model = $local_backend_models[$task_key] ?? "";
$row_style = "";
if ($task_key === "image" && empty($local_backend_image_enabled)) {
$row_style = "display: none;";
}
?>
<tr id="wpaw-ce-row-<?php echo esc_attr(
$task_key,
); ?>" style="<?php echo esc_attr($row_style); ?>">
<td style="vertical-align:middle"><?php echo esc_html(
ucfirst($task_key),
); ?></td>
<td>
<input class="field-control wpaw-ce-model" type="text"
name="wp_agentic_writer_settings[local_backend_models][<?php echo esc_attr(
$task_key,
); ?>]"
value="<?php echo esc_attr($task_model); ?>"
placeholder="gpt-4o-mini"
data-task="<?php echo esc_attr($task_key); ?>">
</td>
</tr>
<?php
endforeach; ?>
</tbody>
</table>
<label class="switch-row" style="margin-top:14px">
<input type="checkbox"
name="wp_agentic_writer_settings[allow_openrouter_fallback]"
value="1" <?php checked($allow_openrouter_fallback); ?>>
<span class="switch"></span>
<span><?php esc_html_e(
"Allow OpenRouter fallback when custom endpoint is unreachable",
"wp-agentic-writer",
); ?></span>
</label>
</div>
</div>
</div>
<script>
(function(){
var toggle = document.getElementById('wpaw-ce-enabled');
var panel = document.getElementById('wpaw-ce-routing');
if (toggle && panel) {
toggle.addEventListener('change', function(){
panel.hidden = !this.checked;
});
}
var imgToggle = document.getElementById('wpaw-ce-image-enabled');
var imgPanel = document.getElementById('wpaw-ce-image-panel');
var imgTestBtn = document.getElementById('wpaw-test-local-image');
var imgRow = document.getElementById('wpaw-ce-row-image');
if (imgToggle && imgPanel) {
imgToggle.addEventListener('change', function(){
imgPanel.hidden = !this.checked;
if (imgTestBtn) {
imgTestBtn.style.display = this.checked ? 'inline-block' : 'none';
}
if (imgRow) {
imgRow.style.display = this.checked ? '' : 'none';
}
});
}
})();
</script>

View File

@@ -0,0 +1,108 @@
<?php
/**
* Settings V2: MEMANTO.
*
* @package WP_Agentic_Writer
*/
if (!defined("ABSPATH")) {
exit();
} ?>
<div class="section-head"><div><p class="eyebrow"><?php esc_html_e(
"Memory",
"wp-agentic-writer",
); ?></p><h2><?php esc_html_e(
"MEMANTO Context Keeper",
"wp-agentic-writer",
); ?></h2><p><?php esc_html_e(
"Optional persistent memory for agentic writing sessions.",
"wp-agentic-writer",
); ?></p></div><span class="status <?php echo $memanto_enabled
? "connected"
: "warn"; ?>"><?php echo $memanto_enabled
? esc_html__("Enabled", "wp-agentic-writer")
: esc_html__("Optional", "wp-agentic-writer"); ?></span></div>
<div class="panel">
<div class="panel-head"><div class="panel-title"><h3><?php esc_html_e(
"Integration",
"wp-agentic-writer",
); ?></h3><p><?php esc_html_e(
"Connect your MEMANTO instance and Moorcheh key.",
"wp-agentic-writer",
); ?></p></div><button type="button" class="btn btn-small" id="wpaw-test-memanto"><?php esc_html_e(
"Test connection",
"wp-agentic-writer",
); ?></button></div>
<div class="panel-body">
<label class="switch-row"><input type="checkbox" name="wp_agentic_writer_settings[memanto_enabled]" value="1" <?php checked(
$memanto_enabled,
); ?>><span class="switch"></span><span><?php esc_html_e(
"Enable MEMANTO",
"wp-agentic-writer",
); ?></span></label>
<div class="grid-2" style="margin-top:14px">
<div class="field">
<label for="memanto_url"><?php esc_html_e(
"Instance URL",
"wp-agentic-writer",
); ?></label>
<input class="field-control" type="url" id="memanto_url" name="wp_agentic_writer_settings[memanto_url]" value="<?php echo esc_attr(
$memanto_url,
); ?>" placeholder="https://your-memanto-instance.com">
</div>
<div class="field">
<label for="memanto_license_key"><?php esc_html_e(
"Instance license key",
"wp-agentic-writer",
); ?></label>
<input class="field-control" type="text" id="memanto_license_key" name="wp_agentic_writer_settings[memanto_license_key]" value="<?php echo esc_attr(
$memanto_license_key,
); ?>">
</div>
</div>
<div class="field" style="margin-top:14px">
<label for="memanto_moorcheh_key"><?php esc_html_e(
"Moorcheh API key",
"wp-agentic-writer",
); ?></label>
<div class="password-row">
<input class="field-control" type="password" id="memanto_moorcheh_key" name="wp_agentic_writer_settings[memanto_moorcheh_key]" value="<?php echo esc_attr(
$memanto_moorcheh_key,
); ?>">
<button type="button" class="btn" data-aw2-toggle-password="#memanto_moorcheh_key"><?php esc_html_e(
"Show",
"wp-agentic-writer",
); ?></button>
</div>
</div>
</div>
</div>
<div class="panel"><div class="panel-head"><div class="panel-title"><h3><?php esc_html_e(
"What MEMANTO does",
"wp-agentic-writer",
); ?></h3><p><?php esc_html_e(
"Keeps preferences and context across writing sessions.",
"wp-agentic-writer",
); ?></p></div></div><div class="panel-body grid-3"><div class="guide-card"><h3><?php esc_html_e(
"Remembers context",
"wp-agentic-writer",
); ?></h3><p class="help"><?php esc_html_e(
"Carry preferences across posts and refreshes.",
"wp-agentic-writer",
); ?></p></div><div class="guide-card"><h3><?php esc_html_e(
"Reduces tokens",
"wp-agentic-writer",
); ?></h3><p class="help"><?php esc_html_e(
"Recall relevant memory instead of resending all context.",
"wp-agentic-writer",
); ?></p></div><div class="guide-card"><h3><?php esc_html_e(
"Optional",
"wp-agentic-writer",
); ?></h3><p class="help"><?php esc_html_e(
"Agentic Writer works without MEMANTO.",
"wp-agentic-writer",
); ?></p></div></div></div>

View File

@@ -0,0 +1,351 @@
<?php
/**
* Settings V2: Models.
*
* @package WP_Agentic_Writer
*/
if (!defined("ABSPATH")) {
exit();
}
$task_labels = [
"chat" => __("Chat", "wp-agentic-writer"),
"clarity" => __("Clarity", "wp-agentic-writer"),
"planning" => __("Planning", "wp-agentic-writer"),
"writing" => __("Writing", "wp-agentic-writer"),
"refinement" => __("Refinement", "wp-agentic-writer"),
"image" => __("Image", "wp-agentic-writer"),
];
$model_values = compact(
"chat_model",
"clarity_model",
"planning_model",
"writing_model",
"refinement_model",
"image_model",
);
?>
<div class="section-head"><div><p class="eyebrow"><?php esc_html_e(
"OpenRouter Connection",
"wp-agentic-writer",
); ?></p><h2><?php esc_html_e(
"OpenRouter",
"wp-agentic-writer",
); ?></h2><p><?php esc_html_e(
"Choose presets, assign models by task, and manage web search features.",
"wp-agentic-writer",
); ?></p></div><button type="button" class="btn" id="wpaw-refresh-models"><?php esc_html_e(
"Refresh models",
"wp-agentic-writer",
); ?></button></div>
<div class="subtab-nav" role="tablist">
<button type="button" class="subtab-btn" role="tab" aria-selected="true" data-aw2-subtab-target="or-connection">Connection</button>
<button type="button" class="subtab-btn" role="tab" aria-selected="false" data-aw2-subtab-target="or-models">Models</button>
</div>
<!-- =======================
TAB: CONNECTION
======================= -->
<div class="subtab-panel active" id="or-connection">
<div class="panel">
<div class="panel-head">
<div class="panel-title"><h3><?php esc_html_e(
"API configuration",
"wp-agentic-writer",
); ?></h3><p><?php esc_html_e(
"OpenRouter powers cloud model access.",
"wp-agentic-writer",
); ?></p></div>
<button type="button" class="btn btn-small" id="wpaw-test-api-key"><?php esc_html_e(
"Test connection",
"wp-agentic-writer",
); ?></button>
</div>
<div class="panel-body">
<div class="field">
<label for="openrouter_api_key"><?php esc_html_e(
"OpenRouter API key",
"wp-agentic-writer",
); ?></label>
<div class="password-row">
<input class="field-control" type="password" id="openrouter_api_key" name="wp_agentic_writer_settings[openrouter_api_key]" value="<?php echo esc_attr(
$api_key,
); ?>" placeholder="sk-or-v1-...">
<button type="button" class="btn" data-aw2-toggle-password="#openrouter_api_key"><?php esc_html_e(
"Show",
"wp-agentic-writer",
); ?></button>
</div>
<p class="help"><?php esc_html_e(
"Stored in WordPress options. Used for model, image, and OpenRouter search requests.",
"wp-agentic-writer",
); ?></p>
</div>
</div>
</div>
<div class="panel">
<div class="panel-head"><div class="panel-title"><h3><?php esc_html_e(
"Budget & cost tracking",
"wp-agentic-writer",
); ?></h3><p><?php esc_html_e(
"Track monthly usage and prevent surprise spend.",
"wp-agentic-writer",
); ?></p></div><span class="status <?php echo esc_attr(
"danger" === $budget_status
? "error"
: ("warning" === $budget_status
? "warn"
: "connected"),
); ?>"><?php echo esc_html(
number_format_i18n($budget_percent, 1),
); ?>%</span></div>
<div class="panel-body">
<div class="grid-3">
<div class="metric-card"><div class="metric-value">$<?php echo esc_html(
number_format_i18n($monthly_used, 2),
); ?></div><div class="metric-label"><?php esc_html_e(
"Used this month",
"wp-agentic-writer",
); ?></div></div>
<div class="metric-card"><div class="metric-value">$<?php echo esc_html(
number_format_i18n($monthly_budget, 2),
); ?></div><div class="metric-label"><?php esc_html_e(
"Monthly budget",
"wp-agentic-writer",
); ?></div></div>
<div class="metric-card"><div class="metric-value"><?php echo esc_html(
number_format_i18n($budget_percent, 1),
); ?>%</div><div class="progress"><span style="width: <?php echo esc_attr(
min(100, $budget_percent),
); ?>%"></span></div><div class="metric-label"><?php esc_html_e(
"Budget usage",
"wp-agentic-writer",
); ?></div></div>
</div>
<div class="budget-controls grid-2" style="margin-top:16px">
<div class="field">
<label for="monthly_budget"><?php esc_html_e(
"Monthly budget (USD)",
"wp-agentic-writer",
); ?></label>
<input class="field-control" type="number" min="0" step="0.01" id="monthly_budget" name="wp_agentic_writer_settings[monthly_budget]" value="<?php echo esc_attr(
$monthly_budget,
); ?>">
</div>
<div class="field">
<label><?php esc_html_e("Enable cost tracking", "wp-agentic-writer"); ?></label>
<label class="switch-row" style="margin-top:4px"><input type="checkbox" name="wp_agentic_writer_settings[cost_tracking_enabled]" value="1" <?php checked(
$cost_tracking_enabled,
); ?>><span class="switch"></span><span><?php esc_html_e(
"Show usage estimates in the editor sidebar.",
"wp-agentic-writer",
); ?></span></label>
</div>
</div>
</div>
</div>
<div class="panel"><div class="panel-head"><div class="panel-title"><h3><?php esc_html_e(
"OpenRouter provider routing",
"wp-agentic-writer",
); ?></h3><p><?php esc_html_e(
"Optional BYOK/provider controls.",
"wp-agentic-writer",
); ?></p></div></div><div class="panel-body">
<label class="switch-row"><input type="checkbox" id="openrouter_provider_routing_enabled" name="wp_agentic_writer_settings[openrouter_provider_routing_enabled]" value="1" <?php checked(
$openrouter_provider_routing_enabled,
); ?> data-aw2-toggle-panel="#wpaw2-provider-routing-fields"><span class="switch"></span><span><?php esc_html_e(
"Enable provider routing",
"wp-agentic-writer",
); ?></span></label>
<div id="wpaw2-provider-routing-fields" class="provider-routing-fields" <?php echo $openrouter_provider_routing_enabled
? ""
: "hidden"; ?>>
<div class="field-label-row"><span><?php esc_html_e(
"Provider slug",
"wp-agentic-writer",
); ?></span><span class="help"><?php esc_html_e(
"Applies to the slug input and provider routing behavior below.",
"wp-agentic-writer",
); ?></span></div>
<div class="grid-3 provider-routing-grid"><div class="field"><input class="field-control" type="text" aria-label="<?php esc_attr_e(
"Provider slug",
"wp-agentic-writer",
); ?>" name="wp_agentic_writer_settings[openrouter_provider_slug]" value="<?php echo esc_attr(
$openrouter_provider_slug,
); ?>" placeholder="openai"></div><label class="switch-row"><input type="checkbox" name="wp_agentic_writer_settings[openrouter_provider_only]" value="1" <?php checked(
$openrouter_provider_only,
); ?>><span class="switch"></span><span><?php esc_html_e(
"Only provider",
"wp-agentic-writer",
); ?></span></label><label class="switch-row"><input type="checkbox" name="wp_agentic_writer_settings[openrouter_allow_provider_fallbacks]" value="1" <?php checked(
$openrouter_allow_provider_fallbacks,
); ?>><span class="switch"></span><span><?php esc_html_e(
"Allow fallback",
"wp-agentic-writer",
); ?></span></label></div>
</div>
</div></div>
</div>
<!-- =======================
TAB: MODELS
======================= -->
<div class="subtab-panel" id="or-models">
<div class="panel"><div class="panel-head"><div class="panel-title"><h3><?php esc_html_e(
"Quick presets",
"wp-agentic-writer",
); ?></h3><p><?php esc_html_e(
"Apply common model combinations.",
"wp-agentic-writer",
); ?></p></div></div><div class="panel-body grid-3">
<button type="button" class="preset-card" data-aw2-preset="budget">
<span class="preset-tier-label"><?php esc_html_e(
"Budget",
"wp-agentic-writer",
); ?></span>
<span class="preset-price">$0<span class="preset-price-cents">.06</span></span>
<span class="preset-price-unit"><?php esc_html_e(
"per article",
"wp-agentic-writer",
); ?></span>
<span class="preset-divider"></span>
<span class="preset-models">
<span class="preset-model-row"><span class="preset-model-dot" style="background:#4285f4"></span><span class="preset-model-name">Gemini 2.5 Flash</span><span class="preset-model-role"><?php esc_html_e(
"Chat · Plan · Clarity",
"wp-agentic-writer",
); ?></span></span>
<span class="preset-model-row"><span class="preset-model-dot" style="background:#ff7000"></span><span class="preset-model-name">Mistral Small</span><span class="preset-model-role"><?php esc_html_e(
"Writing",
"wp-agentic-writer",
); ?></span></span>
<span class="preset-model-row"><span class="preset-model-dot" style="background:#10a37f"></span><span class="preset-model-name">GPT-4o</span><span class="preset-model-role"><?php esc_html_e(
"Image",
"wp-agentic-writer",
); ?></span></span>
</span>
</button>
<button type="button" class="preset-card active" data-aw2-preset="balanced">
<span class="preset-tier-label"><?php esc_html_e(
"Balanced",
"wp-agentic-writer",
); ?> <span class="preset-badge"><?php esc_html_e(
"Recommended",
"wp-agentic-writer",
); ?></span></span>
<span class="preset-price">$0<span class="preset-price-cents">.14</span></span>
<span class="preset-price-unit"><?php esc_html_e(
"per article",
"wp-agentic-writer",
); ?></span>
<span class="preset-divider"></span>
<span class="preset-models">
<span class="preset-model-row"><span class="preset-model-dot" style="background:#4285f4"></span><span class="preset-model-name">Gemini 2.5 Flash</span><span class="preset-model-role"><?php esc_html_e(
"Chat · Plan · Clarity",
"wp-agentic-writer",
); ?></span></span>
<span class="preset-model-row"><span class="preset-model-dot" style="background:#d97757"></span><span class="preset-model-name">Claude Sonnet 4</span><span class="preset-model-role"><?php esc_html_e(
"Writing · Refinement",
"wp-agentic-writer",
); ?></span></span>
<span class="preset-model-row"><span class="preset-model-dot" style="background:#10a37f"></span><span class="preset-model-name">GPT-4o</span><span class="preset-model-role"><?php esc_html_e(
"Image",
"wp-agentic-writer",
); ?></span></span>
</span>
</button>
<button type="button" class="preset-card" data-aw2-preset="premium">
<span class="preset-tier-label"><?php esc_html_e(
"Premium",
"wp-agentic-writer",
); ?></span>
<span class="preset-price">$0<span class="preset-price-cents">.31</span></span>
<span class="preset-price-unit"><?php esc_html_e(
"per article",
"wp-agentic-writer",
); ?></span>
<span class="preset-divider"></span>
<span class="preset-models">
<span class="preset-model-row"><span class="preset-model-dot" style="background:#4285f4"></span><span class="preset-model-name">Gemini 3 Flash</span><span class="preset-model-role"><?php esc_html_e(
"Chat · Plan",
"wp-agentic-writer",
); ?></span></span>
<span class="preset-model-row"><span class="preset-model-dot" style="background:#d97757"></span><span class="preset-model-name">Claude Sonnet 4</span><span class="preset-model-role"><?php esc_html_e(
"Clarity",
"wp-agentic-writer",
); ?></span></span>
<span class="preset-model-row"><span class="preset-model-dot" style="background:#10a37f"></span><span class="preset-model-name">GPT-4.1</span><span class="preset-model-role"><?php esc_html_e(
"Writing · Refinement",
"wp-agentic-writer",
); ?></span></span>
<span class="preset-model-row"><span class="preset-model-dot" style="background:#10a37f"></span><span class="preset-model-name">GPT-4o</span><span class="preset-model-role"><?php esc_html_e(
"Image",
"wp-agentic-writer",
); ?></span></span>
</span>
</button>
</div></div>
<div class="panel"><div class="panel-head"><div class="panel-title"><h3><?php esc_html_e(
"Task model assignments",
"wp-agentic-writer",
); ?></h3><p><?php esc_html_e(
"Each workflow stage can use a specialized model.",
"wp-agentic-writer",
); ?></p></div><span class="status connected" id="wpaw2-cost-estimate">~$0.14</span></div><div class="panel-body grid-2">
<?php foreach ($task_labels as $task_key => $task_label):
$field =
"writing" === $task_key ? "writing_model" : $task_key . "_model"; ?>
<div class="field"><label for="<?php echo esc_attr(
$field,
); ?>"><?php echo esc_html(
$task_label,
); ?></label><select class="field-control wpaw2-model-select" id="<?php echo esc_attr(
$field,
); ?>" name="wp_agentic_writer_settings[<?php echo esc_attr(
$field,
); ?>]"><option value="<?php echo esc_attr(
$model_values[$field] ?? "",
); ?>"><?php echo esc_html(
$model_values[$field] ?? "",
); ?></option></select><p class="help"><?php echo esc_html(
ucfirst($task_key),
); ?> <?php esc_html_e("stage model.", "wp-agentic-writer"); ?></p></div>
<?php
endforeach; ?>
</div></div>
<div class="panel"><div class="panel-head"><div class="panel-title"><h3><?php esc_html_e(
"Custom models",
"wp-agentic-writer",
); ?></h3><p><?php esc_html_e(
"Add exact model IDs not returned by the API.",
"wp-agentic-writer",
); ?></p></div><button type="button" class="btn btn-small" id="wpaw2-add-custom-model"><?php esc_html_e(
"Add model",
"wp-agentic-writer",
); ?></button></div><div class="panel-body" id="wpaw2-custom-models">
<?php foreach ((array) $custom_models as $custom_model): ?>
<div class="custom-row"><input class="field-control" type="text" value="<?php echo esc_attr(
$custom_model["id"] ?? "",
); ?>" placeholder="provider/model-id"><input class="field-control" type="text" value="<?php echo esc_attr(
$custom_model["name"] ?? "",
); ?>" placeholder="Display name"><select class="field-control"><option value="text" <?php selected(
$custom_model["type"] ?? "text",
"text",
); ?>>Text</option><option value="image" <?php selected(
$custom_model["type"] ?? "text",
"image",
); ?>>Image</option></select><button type="button" class="btn btn-danger btn-small" data-remove><?php esc_html_e(
"Remove",
"wp-agentic-writer",
); ?></button></div>
<?php endforeach; ?>
</div></div>
</div>

View File

@@ -0,0 +1,150 @@
<?php
/**
* Settings V2: Tools.
*
* @package WP_Agentic_Writer
*/
if (!defined("ABSPATH")) {
exit();
} ?>
<div class="section-head">
<div>
<p class="eyebrow"><?php esc_html_e("Capabilities", "wp-agentic-writer"); ?></p>
<h2><?php esc_html_e("Tools", "wp-agentic-writer"); ?></h2>
<p><?php esc_html_e(
"Configure external tools and APIs that give your AI agent superpowers like internet access.",
"wp-agentic-writer",
); ?></p>
</div>
</div>
<div class="panel">
<div class="panel-head">
<div class="panel-title">
<h3><?php esc_html_e("Web Search", "wp-agentic-writer"); ?></h3>
<p><?php esc_html_e(
"Allow the agent to search the internet for fresh context. OpenRouter natively supports this, but you can bypass external fees by plugging in your own search API.",
"wp-agentic-writer",
); ?></p>
</div>
<label class="switch-row" style="margin:0"><input type="checkbox" name="wp_agentic_writer_settings[web_search_enabled]" value="1" <?php checked(
$web_search_enabled,
); ?>><span class="switch"></span></label>
</div>
<div class="panel-body">
<div class="grid-2">
<div class="field"><label for="search_engine"><?php esc_html_e(
"Search engine format",
"wp-agentic-writer",
); ?></label>
<select class="field-control" id="search_engine" name="wp_agentic_writer_settings[search_engine]">
<option value="auto" <?php selected(
$search_engine,
"auto",
); ?>>Auto (OpenRouter if available)</option>
<option value="openrouter" <?php selected(
$search_engine,
"openrouter",
); ?>>OpenRouter Native</option>
<option value="9router" <?php selected(
$search_engine,
"9router",
); ?>>9Router (Proxy)</option>
<option value="tavily" <?php selected(
$search_engine,
"tavily",
); ?>>Tavily API</option>
<option value="serper" <?php selected(
$search_engine,
"serper",
); ?>>Serper.dev (Google)</option>
<option value="brave" <?php selected(
$search_engine,
"brave",
); ?>>Brave Search API</option>
</select>
</div>
<div class="field"><label for="search_depth"><?php esc_html_e(
"Search depth",
"wp-agentic-writer",
); ?></label>
<select class="field-control" id="search_depth" name="wp_agentic_writer_settings[search_depth]">
<option value="light" <?php selected($search_depth, "light"); ?>>Light</option>
<option value="medium" <?php selected(
$search_depth,
"medium",
); ?>>Medium</option>
<option value="deep" <?php selected($search_depth, "deep"); ?>>Deep</option>
</select>
</div>
</div>
<!-- Custom Search Wrapper -->
<div id="wpaw2-custom-search-fields" style="margin-top:20px; <?php echo in_array(
$search_engine,
["auto", "openrouter"],
)
? "display:none;"
: ""; ?>">
<div class="field" style="margin-bottom:12px;">
<label for="custom_search_url"><?php esc_html_e(
"Search Base URL",
"wp-agentic-writer",
); ?></label>
<input class="field-control" type="url" id="custom_search_url" name="wp_agentic_writer_settings[custom_search_url]" value="<?php echo esc_attr(
$custom_search_url ?? "",
); ?>" placeholder="e.g. http://localhost:20128/v1/search">
</div>
<div class="field">
<label for="brave_search_api_key"><?php esc_html_e(
"Search API key",
"wp-agentic-writer",
); ?></label>
<div class="password-row">
<input class="field-control" type="password" id="brave_search_api_key" name="wp_agentic_writer_settings[brave_search_api_key]" value="<?php echo esc_attr(
$brave_search_api_key,
); ?>" placeholder="sk-...">
<button type="button" class="btn" data-aw2-toggle-password="#brave_search_api_key"><?php esc_html_e(
"Show",
"wp-agentic-writer",
); ?></button>
</div>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const searchEngine = document.getElementById('search_engine');
const searchFields = document.getElementById('wpaw2-custom-search-fields');
const searchUrl = document.getElementById('custom_search_url');
if (searchEngine && searchFields) {
searchEngine.addEventListener('change', function() {
if (this.value === 'auto' || this.value === 'openrouter') {
searchFields.style.display = 'none';
} else {
searchFields.style.display = 'block';
// Auto-fill standard endpoints if empty or if currently matching another default
const defaultUrls = [
'',
'http://localhost:20128/v1/search',
'https://api.tavily.com/search',
'https://google.serper.dev/search',
'https://api.search.brave.com/res/v1/web/search'
];
if (defaultUrls.includes(searchUrl.value.trim())) {
if (this.value === '9router') searchUrl.value = 'http://localhost:20128/v1/search';
if (this.value === 'tavily') searchUrl.value = 'https://api.tavily.com/search';
if (this.value === 'serper') searchUrl.value = 'https://google.serper.dev/search';
if (this.value === 'brave') searchUrl.value = 'https://api.search.brave.com/res/v1/web/search';
}
}
});
}
});
</script>