Phase 1: Core Client
- New class-memanto-client.php: Singleton PHP client for MEMANTO API v2
- Health check with 5-min transient caching
- Agent CRUD (ensure, activate, deactivate sessions)
- Memory operations (remember, batch_remember, recall, recall_recent)
- Auto re-activation on expired session tokens (401 retry)
Phase 2: Write-Through Memory Hooks
- New class-memanto-context-enhancer.php: Orchestrates remember/recall
- Fires on: user message, plan generated/approved/rejected,
section written, block refined, config saved, session start/end
- All hooks via do_action() — zero coupling to MEMANTO when disabled
Phase 3: Context Enrichment
- Context builder injects recalled memories into AI prompts
via build_memanto_context() in build_working_context()
- 3-recall strategy: recent post memories, semantic search, user preferences
- Deduplication by content hash
Phase 4: Cross-Session Restore
- New REST endpoints: /memanto/restore, /memanto/preferences
- restore_session() recalls 15 recent memories + user preferences on editor load
- build_session_restore_message() creates AI-ready system message
- get_user_preferences_for_new_post() extracts tone/audience/length/language
- Frontend: 🧠 Restored badge in status bar with memory count tooltip
- Preference carry-over: auto-fills post config from stored user preferences
- deactivate_session() called on session end (triggers MEMANTO summary)
- Badge clears on new conversation start
Settings UI:
- MEMANTO Context Keeper section with enable toggle, URL, API key, test connection
- Settings registered via class-settings-v2.php + tab-memanto.php view
Graceful degradation: all MEMANTO calls guarded by is_active(),
frontend catches silently, plugin works identically when disabled.
247 lines
11 KiB
PHP
247 lines
11 KiB
PHP
<?php
|
|
/**
|
|
* Settings Layout - Bootstrap 5 wrapper
|
|
*
|
|
* @package WP_Agentic_Writer
|
|
* @var array $view_data Prepared view data from class-settings-v2.php
|
|
*/
|
|
|
|
if (!defined("ABSPATH")) {
|
|
exit();
|
|
}
|
|
|
|
// Extract view data for easier access
|
|
extract($view_data);
|
|
?>
|
|
<div class="wrap wpaw-settings-v2-wrap">
|
|
<!-- Agentic IDE Split View Layout -->
|
|
<div class="wpaw-ide-container d-flex">
|
|
|
|
<!-- Left Sidebar: Settings Navigation -->
|
|
<div class="wpaw-sidebar-nav flex-shrink-0">
|
|
<!-- Header inside Sidebar -->
|
|
<div class="wpaw-sidebar-header p-3 mb-2 border-bottom border-dark">
|
|
<div class="d-flex align-items-center gap-2">
|
|
<img src="<?php echo esc_url(WP_AGENTIC_WRITER_URL . "assets/img/icon.svg"); ?>"
|
|
alt="WP Agentic Writer"
|
|
style="width: 24px; height: 24px; filter: invert(1)">
|
|
<h1 class="h6 mb-0 text-white fw-bold">Agentic Writer</h1>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Search Placeholder (Phase 2) -->
|
|
<!-- <div class="px-3 mb-3"><input type="text" class="form-control form-control-sm wpaw-search-input" placeholder="Search settings..."></div> -->
|
|
|
|
<!-- Navigation Tree -->
|
|
<div class="wpaw-nav-tree px-2">
|
|
<div class="text-uppercase small text-secondary fw-semibold mb-2 px-2" style="font-size: 0.7rem; tracking: 1px;">Configuration</div>
|
|
<ul class="nav flex-column gap-1" id="wpaw-settings-tabs" role="tablist">
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link active w-100 text-start d-flex align-items-center gap-2" id="general-tab" data-bs-toggle="pill" data-bs-target="#general" type="button" role="tab" aria-controls="general" aria-selected="true">
|
|
<i class="bi bi-sliders"></i>
|
|
<?php esc_html_e("General", "wp-agentic-writer"); ?>
|
|
</button>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link w-100 text-start d-flex align-items-center gap-2" id="models-tab" data-bs-toggle="pill" data-bs-target="#models" type="button" role="tab" aria-controls="models" aria-selected="false">
|
|
<i class="bi bi-stars"></i>
|
|
<?php esc_html_e("AI Models", "wp-agentic-writer"); ?>
|
|
</button>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link w-100 text-start d-flex align-items-center gap-2" id="local-backend-tab" data-bs-toggle="pill" data-bs-target="#local-backend" type="button" role="tab" aria-controls="local-backend" aria-selected="false">
|
|
<i class="bi bi-house-fill"></i>
|
|
<?php esc_html_e("Local Backend", "wp-agentic-writer"); ?>
|
|
</button>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link w-100 text-start d-flex align-items-center gap-2" id="memanto-tab" data-bs-toggle="pill" data-bs-target="#memanto" type="button" role="tab" aria-controls="memanto" aria-selected="false">
|
|
<i class="bi bi-cpu"></i>
|
|
<?php esc_html_e("MEMANTO", "wp-agentic-writer"); ?>
|
|
</button>
|
|
</li>
|
|
|
|
<div class="text-uppercase small text-secondary fw-semibold mb-2 mt-4 px-2" style="font-size: 0.7rem; tracking: 1px;">Analytics & Docs</div>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link w-100 text-start d-flex align-items-center gap-2" id="cost-log-tab" data-bs-toggle="pill" data-bs-target="#cost-log" type="button" role="tab" aria-controls="cost-log" aria-selected="false">
|
|
<i class="bi bi-graph-up"></i>
|
|
<?php esc_html_e("OpenRouter Cost Log", "wp-agentic-writer"); ?>
|
|
</button>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link w-100 text-start d-flex align-items-center gap-2" id="guide-tab" data-bs-toggle="pill" data-bs-target="#guide" type="button" role="tab" aria-controls="guide" aria-selected="false">
|
|
<i class="bi bi-book"></i>
|
|
<?php esc_html_e("Model Guide", "wp-agentic-writer"); ?>
|
|
</button>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Right Content Pane: Settings Forms -->
|
|
<div class="wpaw-content-pane flex-grow-1 d-flex flex-column h-100">
|
|
<form method="post" action="options.php" id="wpaw-settings-form" class="h-100 d-flex flex-column">
|
|
<?php settings_fields("wp_agentic_writer_settings"); ?>
|
|
|
|
<!-- Workflow Pipeline Progress -->
|
|
<div class="wpaw-workflow-progress wpaw-workflow-compact mb-4" id="wpaw-workflow-display">
|
|
<div class="wpaw-progress-header">
|
|
<span class="wpaw-progress-title">Writing Pipeline</span>
|
|
<span class="wpaw-progress-status" id="wpaw-workflow-status">Idle</span>
|
|
</div>
|
|
<div class="wpaw-progress-steps">
|
|
<!-- Step 1: Context -->
|
|
<div class="wpaw-step" data-step="1" data-tooltip="Context: Load post & keyword">
|
|
<div class="wpaw-step-circle">
|
|
<span class="wpaw-step-icon">📋</span>
|
|
</div>
|
|
<span class="wpaw-step-label">Context</span>
|
|
</div>
|
|
<!-- Connector -->
|
|
<div class="wpaw-step-connector" data-connector="1"></div>
|
|
<!-- Step 2: Planning -->
|
|
<div class="wpaw-step" data-step="2" data-tooltip="Planning: Create outline">
|
|
<div class="wpaw-step-circle">
|
|
<span class="wpaw-step-icon">📝</span>
|
|
</div>
|
|
<span class="wpaw-step-label">Planning</span>
|
|
</div>
|
|
<!-- Connector -->
|
|
<div class="wpaw-step-connector" data-connector="2"></div>
|
|
<!-- Step 3: Writing -->
|
|
<div class="wpaw-step" data-step="3" data-tooltip="Writing: Generate content">
|
|
<div class="wpaw-step-circle">
|
|
<span class="wpaw-step-icon">✍️</span>
|
|
</div>
|
|
<span class="wpaw-step-label">Writing</span>
|
|
</div>
|
|
<!-- Connector -->
|
|
<div class="wpaw-step-connector" data-connector="3"></div>
|
|
<!-- Step 4: Refinement -->
|
|
<div class="wpaw-step" data-step="4" data-tooltip="Refinement: Polish & optimize">
|
|
<div class="wpaw-step-circle">
|
|
<span class="wpaw-step-icon">🎯</span>
|
|
</div>
|
|
<span class="wpaw-step-label">Refinement</span>
|
|
</div>
|
|
<!-- Connector -->
|
|
<div class="wpaw-step-connector" data-connector="4"></div>
|
|
<!-- Step 5: Done -->
|
|
<div class="wpaw-step" data-step="5" data-tooltip="Complete: Ready to publish">
|
|
<div class="wpaw-step-circle">
|
|
<span class="wpaw-step-icon">✅</span>
|
|
</div>
|
|
<span class="wpaw-step-label">Done</span>
|
|
</div>
|
|
</div>
|
|
<div class="wpaw-step-message mt-3" id="wpaw-workflow-message" style="display: none;"></div>
|
|
</div>
|
|
|
|
<!-- Scrollable Tab Content Area -->
|
|
<div class="wpaw-tab-scroll-area flex-grow-1 p-4 p-md-5 overflow-auto">
|
|
<div class="tab-content" id="wpaw-settings-tab-content">
|
|
<!-- General Tab -->
|
|
<div class="tab-pane fade show active" id="general" role="tabpanel" aria-labelledby="general-tab">
|
|
<div class="mb-4 pb-3 border-bottom border-dark">
|
|
<h2 class="h4 text-white m-0">General Settings</h2>
|
|
<p class="text-secondary small mt-1">Configure global API keys, budget, and content parameters.</p>
|
|
</div>
|
|
<?php include WP_AGENTIC_WRITER_DIR . "views/settings/tab-general.php"; ?>
|
|
</div>
|
|
|
|
<!-- Models Tab -->
|
|
<div class="tab-pane fade" id="models" role="tabpanel" aria-labelledby="models-tab">
|
|
<div class="mb-4 pb-3 border-bottom border-dark">
|
|
<h2 class="h4 text-white m-0">AI Models</h2>
|
|
<p class="text-secondary small mt-1">Select logic engines for different stages of the writing pipeline.</p>
|
|
</div>
|
|
<?php include WP_AGENTIC_WRITER_DIR . "views/settings/tab-models.php"; ?>
|
|
</div>
|
|
|
|
<!-- Local Backend Tab -->
|
|
<div class="tab-pane fade" id="local-backend" role="tabpanel" aria-labelledby="local-backend-tab">
|
|
<div class="mb-4 pb-3 border-bottom border-dark">
|
|
<h2 class="h4 text-white m-0">Local Backend</h2>
|
|
<p class="text-secondary small mt-1">Configure connections to local LM Studio or Ollama instances.</p>
|
|
</div>
|
|
<?php include WP_AGENTIC_WRITER_DIR . "views/settings/tab-local-backend.php"; ?>
|
|
</div>
|
|
|
|
<!-- MEMANTO Tab -->
|
|
<div class="tab-pane fade" id="memanto" role="tabpanel" aria-labelledby="memanto-tab">
|
|
<div class="mb-4 pb-3 border-bottom border-dark">
|
|
<h2 class="h4 text-white m-0">MEMANTO Context Keeper</h2>
|
|
<p class="text-secondary small mt-1">Optional persistent memory for your AI writing assistant. The plugin works perfectly without it.</p>
|
|
</div>
|
|
<?php include WP_AGENTIC_WRITER_DIR . "views/settings/tab-memanto.php"; ?>
|
|
</div>
|
|
|
|
<!-- Cost Log Tab -->
|
|
<div class="tab-pane fade" id="cost-log" role="tabpanel" aria-labelledby="cost-log-tab">
|
|
<div class="mb-4 pb-3 border-bottom border-dark">
|
|
<h2 class="h4 text-white m-0">OpenRouter Cost Analytics</h2>
|
|
<p class="text-secondary small mt-1">Track API token usage and expenses across all generations.</p>
|
|
</div>
|
|
<?php include WP_AGENTIC_WRITER_DIR . "views/settings/tab-cost-log.php"; ?>
|
|
</div>
|
|
|
|
<!-- Guide Tab -->
|
|
<div class="tab-pane fade" id="guide" role="tabpanel" aria-labelledby="guide-tab">
|
|
<div class="mb-4 pb-3 border-bottom border-dark">
|
|
<h2 class="h4 text-white m-0">Provider Documentation</h2>
|
|
<p class="text-secondary small mt-1">Reference materials for selecting the right model constraints.</p>
|
|
</div>
|
|
<?php include WP_AGENTIC_WRITER_DIR . "views/settings/tab-guide.php"; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Fixed Bottom Save Bar (Compact) -->
|
|
<div class="wpaw-save-bar p-3 border-top border-dark d-flex justify-content-between align-items-center bg-transparent mt-auto sticky-bottom">
|
|
<div class="text-secondary small d-flex align-items-center gap-2">
|
|
<span class="dashicons dashicons-plugin text-primary"></span>
|
|
<?php printf(
|
|
esc_html__("v%s", "wp-agentic-writer"),
|
|
esc_html(WP_AGENTIC_WRITER_VERSION),
|
|
); ?>
|
|
</div>
|
|
<div class="d-flex gap-2">
|
|
<button type="button" class="btn btn-sm btn-outline-secondary" id="wpaw-reset-settings">
|
|
<?php esc_html_e("Reset Defaults", "wp-agentic-writer"); ?>
|
|
</button>
|
|
<button type="submit" class="btn btn-sm btn-primary px-4 fw-semibold" id="wpaw-save-settings">
|
|
<?php
|
|
$is_mac =
|
|
isset($_SERVER["HTTP_USER_AGENT"]) &&
|
|
strpos(wp_unslash($_SERVER["HTTP_USER_AGENT"]), "Mac OS") !== false;
|
|
$cmd_key = $is_mac ? "⌘" : "Ctrl";
|
|
?>
|
|
<?php esc_html_e(
|
|
"Save Settings",
|
|
"wp-agentic-writer",
|
|
); ?> <kbd class="ms-1 bg-dark text-white border-0 py-0"><?php echo esc_html(
|
|
$cmd_key,
|
|
); ?>+S</kbd>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Toast Container for Notifications -->
|
|
<div class="toast-container position-fixed bottom-0 end-0 p-3">
|
|
<div id="wpaw-toast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
|
|
<div class="toast-header">
|
|
<span class="me-2">✨</span>
|
|
<strong class="me-auto"><?php esc_html_e(
|
|
"WP Agentic Writer",
|
|
"wp-agentic-writer",
|
|
); ?></strong>
|
|
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
|
|
</div>
|
|
<div class="toast-body" id="wpaw-toast-message"></div>
|
|
</div>
|
|
</div>
|