feat: MEMANTO integration — persistent memory for cross-session context (Phases 1-4)

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.
This commit is contained in:
Dwindi Ramadhana
2026-06-08 12:42:04 +07:00
parent 379a72e52d
commit 619d36d3c8
11 changed files with 28226 additions and 18716 deletions

View File

@@ -66,7 +66,9 @@
color: #a7aaad;
text-transform: uppercase;
letter-spacing: 0.05em;
transition: color 0.1s ease, border-color 0.1s ease;
transition:
color 0.1s ease,
border-color 0.1s ease;
margin-bottom: -1px;
}
@@ -176,6 +178,188 @@
background: #525b6b;
}
.wpaw-agent-workspace-card {
background: linear-gradient(135deg, #111827 0%, #1e293b 100%);
border: 1px solid #334155;
border-radius: 12px;
margin: 10px 10px 8px;
padding: 12px;
color: #e5e7eb;
box-shadow: 0 12px 30px rgba(15, 23, 42, 0.28);
}
.wpaw-agent-workspace-card.is-collapsed {
padding: 9px 10px;
}
.wpaw-agent-workspace-header {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
margin-bottom: 10px;
}
.wpaw-agent-workspace-card.is-collapsed .wpaw-agent-workspace-header {
align-items: center;
margin-bottom: 0;
}
.wpaw-agent-workspace-heading {
min-width: 0;
}
.wpaw-agent-workspace-kicker {
color: #93c5fd;
font-size: 10px;
letter-spacing: 0.08em;
text-transform: uppercase;
font-weight: 700;
margin-bottom: 3px;
}
.wpaw-agent-workspace-title {
color: #f8fafc;
font-size: 13px;
font-weight: 700;
line-height: 1.3;
}
.wpaw-agent-workspace-actions {
display: flex;
align-items: center;
gap: 6px;
flex-shrink: 0;
}
.wpaw-agent-workspace-status {
white-space: nowrap;
border-radius: 999px;
border: 1px solid rgba(148, 163, 184, 0.35);
color: #cbd5e1;
background: rgba(15, 23, 42, 0.7);
padding: 4px 8px;
font-size: 10px;
text-transform: capitalize;
}
.wpaw-agent-workspace-toggle {
border: 1px solid rgba(147, 197, 253, 0.35);
border-radius: 999px;
background: rgba(15, 23, 42, 0.42);
color: #bfdbfe;
cursor: pointer;
font-size: 10px;
font-weight: 700;
line-height: 1;
padding: 5px 8px;
}
.wpaw-agent-workspace-toggle:hover,
.wpaw-agent-workspace-toggle:focus {
border-color: #60a5fa;
color: #eff6ff;
outline: none;
}
.wpaw-agent-workspace-status.status-in_progress,
.wpaw-agent-workspace-status.status-paused,
.wpaw-agent-workspace-status.status-running,
.wpaw-agent-workspace-status.status-stopping {
color: #fbbf24;
border-color: rgba(251, 191, 36, 0.45);
background: rgba(113, 63, 18, 0.28);
}
.wpaw-agent-workspace-status.status-completed {
color: #86efac;
border-color: rgba(134, 239, 172, 0.45);
background: rgba(20, 83, 45, 0.28);
}
.wpaw-agent-workspace-status.status-failed {
color: #fca5a5;
border-color: rgba(248, 113, 113, 0.45);
background: rgba(127, 29, 29, 0.28);
}
.wpaw-agent-context-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 8px;
}
.wpaw-agent-context-item {
min-width: 0;
background: rgba(15, 23, 42, 0.52);
border: 1px solid rgba(148, 163, 184, 0.18);
border-radius: 9px;
padding: 8px;
}
.wpaw-agent-context-item span {
display: block;
color: #94a3b8;
font-size: 10px;
text-transform: uppercase;
letter-spacing: 0.04em;
margin-bottom: 4px;
}
.wpaw-agent-context-item strong {
display: block;
color: #f8fafc;
font-size: 12px;
line-height: 1.35;
overflow: hidden;
text-overflow: ellipsis;
}
.wpaw-agent-keyword-input {
width: 100%;
min-height: 26px;
border: 1px solid rgba(147, 197, 253, 0.32);
border-radius: 7px;
background: rgba(15, 23, 42, 0.78);
color: #f8fafc;
font-size: 12px;
padding: 4px 7px;
}
.wpaw-agent-keyword-input:focus {
outline: none;
border-color: #60a5fa;
box-shadow: 0 0 0 1px rgba(96, 165, 250, 0.35);
}
.wpaw-agent-resume-card {
display: flex;
justify-content: space-between;
align-items: center;
gap: 10px;
margin-top: 10px;
padding: 9px;
border-radius: 9px;
background: rgba(59, 130, 246, 0.12);
border: 1px solid rgba(96, 165, 250, 0.28);
}
.wpaw-agent-resume-card strong,
.wpaw-agent-resume-card span {
display: block;
}
.wpaw-agent-resume-card strong {
color: #bfdbfe;
font-size: 12px;
}
.wpaw-agent-resume-card span {
color: #93c5fd;
font-size: 11px;
margin-top: 2px;
}
.wpaw-input-area {
background: #1e2128;
padding: 12px;
@@ -581,7 +765,7 @@ input.wpaw-plan-section-check:checked::before {
}
.wpaw-block-refining::before {
content: 'REFINING';
content: "REFINING";
position: absolute;
top: -12px;
right: 8px;
@@ -618,7 +802,7 @@ input.wpaw-plan-section-check:checked::before {
padding: 12px;
border-radius: 8px;
overflow-x: auto;
font-family: ui-monospace, 'SF Mono', Menlo, monospace;
font-family: ui-monospace, "SF Mono", Menlo, monospace;
font-size: 12px;
border: 1px solid #2d3139;
color: #c8cdd5;
@@ -629,16 +813,18 @@ input.wpaw-plan-section-check:checked::before {
color: #a5d6ff;
padding: 2px 5px;
border-radius: 4px;
font-family: ui-monospace, 'SF Mono', Menlo, monospace;
font-family: ui-monospace, "SF Mono", Menlo, monospace;
font-size: 12px;
}
.wpaw-editor-locked .admin-ui-navigable-region.interface-interface-skeleton__content {
.wpaw-editor-locked
.admin-ui-navigable-region.interface-interface-skeleton__content {
position: relative;
}
.wpaw-editor-locked .admin-ui-navigable-region.interface-interface-skeleton__content::after {
content: '';
.wpaw-editor-locked
.admin-ui-navigable-region.interface-interface-skeleton__content::after {
content: "";
position: absolute;
inset: 0;
background: rgba(255, 255, 255, 0.55);
@@ -894,7 +1080,7 @@ input.wpaw-plan-section-check:checked::before {
}
.wpaw-ai-response .wpaw-response::before {
content: '';
content: "";
position: absolute;
left: -15px;
top: 20px;
@@ -913,7 +1099,7 @@ input.wpaw-plan-section-check:checked::before {
}
.wpaw-streaming-indicator::after {
content: '...';
content: "...";
display: inline-block;
width: 18px;
animation: wpaw-ellipsis 1.1s infinite;
@@ -951,19 +1137,19 @@ input.wpaw-plan-section-check:checked::before {
@keyframes wpaw-ellipsis {
0% {
content: '.';
content: ".";
}
33% {
content: '..';
content: "..";
}
66% {
content: '...';
content: "...";
}
100% {
content: '.';
content: ".";
}
}
@@ -1073,7 +1259,7 @@ input.wpaw-plan-section-check:checked::before {
border-color: #e2e8f0;
}
.wpaw-plan-section-row input[type=checkbox] {
.wpaw-plan-section-row input[type="checkbox"] {
transform: translateY(3px);
}
@@ -1093,7 +1279,8 @@ input.wpaw-plan-section-check:checked::before {
.wpaw-timeline-content {
flex: 1;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
font-family:
-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
color: #c8cdd5;
}
@@ -1181,7 +1368,7 @@ input.wpaw-plan-section-check:checked::before {
z-index: 2;
}
.wpaw-config-tab>*:nth-child(2) {
.wpaw-config-tab > *:nth-child(2) {
margin-top: 60px;
}
@@ -1293,14 +1480,16 @@ input.wpaw-plan-section-check:checked::before {
margin-bottom: 10px;
}
.wpaw-budget-bar~.description {
.wpaw-budget-bar ~ .description {
padding: 0 12px;
}
.wpaw-budget-fill {
height: 100%;
background: linear-gradient(90deg, #4caf50, #66bb6a);
transition: width 0.5s ease, background 0.3s ease;
transition:
width 0.5s ease,
background 0.3s ease;
}
.wpaw-budget-fill.warning {
@@ -1602,7 +1791,7 @@ input.wpaw-plan-section-check:checked::before {
font-size: 13px;
}
.wpaw-previous-answers>div:last-child .wpaw-answer-text {
.wpaw-previous-answers > div:last-child .wpaw-answer-text {
margin-bottom: 0;
}
@@ -1722,11 +1911,11 @@ input.wpaw-plan-section-check:checked::before {
transition: 0.3s;
}
.wpaw-config-toggle input:checked+.wpaw-toggle-slider {
.wpaw-config-toggle input:checked + .wpaw-toggle-slider {
background-color: #2271b1;
}
.wpaw-config-toggle input:checked+.wpaw-toggle-slider:before {
.wpaw-config-toggle input:checked + .wpaw-toggle-slider:before {
transform: translateX(24px);
}
@@ -1755,11 +1944,14 @@ input.wpaw-plan-section-check:checked::before {
display: flex;
}
.wpaw-question-card .wpaw-config-form .wpaw-config-label .wpaw-config-description {
.wpaw-question-card
.wpaw-config-form
.wpaw-config-label
.wpaw-config-description {
font-size: 11px;
}
.wpaw-question-card .wpaw-config-field:has(input[type=text]) {
.wpaw-question-card .wpaw-config-field:has(input[type="text"]) {
flex-direction: column;
}
@@ -1786,7 +1978,7 @@ input.wpaw-plan-section-check:checked::before {
padding-right: 20px;
}
.wpaw-question-card .wpaw-config-form .wpaw-config-field input[type=text] {
.wpaw-question-card .wpaw-config-form .wpaw-config-field input[type="text"] {
background-color: #1a1a1a !important;
}
@@ -1812,13 +2004,12 @@ input.wpaw-plan-section-check:checked::before {
}
.dark-theme .wpaw-question-card textarea::placeholder {
color: #6c6c6c
color: #6c6c6c;
}
.dark-theme .wpaw-question-card textarea::focus,
.dark-theme .wpaw-question-card textarea::active {
border-color: #252830 !important;
;
}
/* ===========================
@@ -1861,7 +2052,6 @@ input.wpaw-plan-section-check:checked::before {
}
@keyframes wpaw-pulse {
0%,
100% {
box-shadow: 0 0 0 0px rgba(34, 113, 177, 0.2);
@@ -1920,8 +2110,9 @@ input.wpaw-plan-section-check:checked::before {
}
@media (max-width: 482px) {
.interface-complementary-area__fill:has(#wp-agentic-writer\:wp-agentic-writer),
.interface-complementary-area__fill:has(
#wp-agentic-writer\:wp-agentic-writer
),
#wp-agentic-writer\:wp-agentic-writer {
width: 100vw !important;
}
@@ -1933,7 +2124,9 @@ input.wpaw-plan-section-check:checked::before {
height: 6px;
border-radius: 50%;
background-color: #3b82f6;
box-shadow: 12px 0 #3b82f6, -12px 0 #3b82f6;
box-shadow:
12px 0 #3b82f6,
-12px 0 #3b82f6;
position: relative;
animation: wpaw-flash 0.5s ease-out infinite alternate;
margin: 0 20px 0 16px;
@@ -1943,17 +2136,23 @@ input.wpaw-plan-section-check:checked::before {
@keyframes wpaw-flash {
0% {
background-color: #93c5fd;
box-shadow: 12px 0 #93c5fd, -12px 0 #3b82f6;
box-shadow:
12px 0 #93c5fd,
-12px 0 #3b82f6;
}
50% {
background-color: #3b82f6;
box-shadow: 12px 0 #93c5fd, -12px 0 #93c5fd;
box-shadow:
12px 0 #93c5fd,
-12px 0 #93c5fd;
}
100% {
background-color: #93c5fd;
box-shadow: 12px 0 #3b82f6, -12px 0 #93c5fd;
box-shadow:
12px 0 #3b82f6,
-12px 0 #93c5fd;
}
}
@@ -1977,7 +2176,8 @@ input.wpaw-plan-section-check:checked::before {
padding: 8px 12px;
background: #1d2227;
color: #fff;
font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
font-family:
ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
font-size: 12px;
border-bottom: 1px solid #3c3c3c;
}
@@ -2004,11 +2204,22 @@ input.wpaw-plan-section-check:checked::before {
animation: statusPulse 1s infinite;
}
.wpaw-status-dot.checking,
.wpaw-status-dot.refining {
background: #60a5fa;
animation: statusPulse 0.8s infinite;
}
.wpaw-status-dot.writing {
background: #2271b1;
animation: statusPulse 0.8s infinite;
}
.wpaw-status-dot.stopping {
background: #f97316;
animation: statusPulse 0.55s infinite;
}
.wpaw-status-dot.complete {
background: #00a32a;
}
@@ -2018,7 +2229,6 @@ input.wpaw-plan-section-check:checked::before {
}
@keyframes statusPulse {
0%,
100% {
opacity: 1;
@@ -2035,6 +2245,22 @@ input.wpaw-plan-section-check:checked::before {
font-weight: 500;
}
.wpaw-memanto-badge {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 2px 8px;
border-radius: 10px;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.02em;
background: rgba(99, 155, 255, 0.15);
color: #93b8ff;
border: 1px solid rgba(99, 155, 255, 0.25);
cursor: default;
white-space: nowrap;
}
.wpaw-status-cost {
color: #a7aaad;
font-size: 11px;
@@ -2047,7 +2273,8 @@ input.wpaw-plan-section-check:checked::before {
flex-direction: column;
overflow-y: auto;
background: #fff;
font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
font-family:
ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
font-size: 13px;
line-height: 1.5;
}
@@ -2127,7 +2354,9 @@ input.wpaw-plan-section-check:checked::before {
/* Agent Response (prose) */
.wpaw-log-entry.agent-response {
border-left-color: #dcdcde;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
font-family:
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans,
Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
}
/* Command Input Area */
@@ -2287,7 +2516,9 @@ input.wpaw-plan-section-check:checked::before {
font-size: 14px;
padding: 2px;
line-height: 1;
transition: color 0.1s ease, transform 0.1s ease;
transition:
color 0.1s ease,
transform 0.1s ease;
}
.wpaw-status-icon-btn:hover {
@@ -2391,11 +2622,11 @@ input.wpaw-plan-section-check:checked::before {
transition: opacity 0.15s ease;
}
.wpaw-web-search-toggle input:checked+.wpaw-web-search-icon {
.wpaw-web-search-toggle input:checked + .wpaw-web-search-icon {
opacity: 1;
}
.wpaw-web-search-toggle input:checked+.wpaw-web-search-icon * {
.wpaw-web-search-toggle input:checked + .wpaw-web-search-icon * {
stroke: #4caf50;
}
@@ -2408,7 +2639,7 @@ input.wpaw-plan-section-check:checked::before {
transition: color 0.15s ease;
}
.wpaw-web-search-toggle input:checked~.wpaw-web-search-label {
.wpaw-web-search-toggle input:checked ~ .wpaw-web-search-label {
color: #4caf50;
}
@@ -2513,6 +2744,17 @@ input.wpaw-plan-section-check:checked::before {
transform: scale(1.05);
}
.wpaw-stop-circle-btn.is-stopping,
.wpaw-stop-circle-btn.is-stopping:hover {
background: #f97316;
cursor: wait;
transform: none;
}
.wpaw-stop-spinner {
animation: wpaw-spin 0.85s linear infinite;
}
.wpaw-command-circle-btn svg {
width: 20px !important;
height: 20px !important;
@@ -2827,10 +3069,37 @@ input.wpaw-plan-section-check:checked::before {
}
.wpaw-seo-check .check-label {
flex: 1;
color: #a7aaad;
min-width: 0;
}
.wpaw-meta-info>button.components-button.is-secondary.is-small {
.wpaw-seo-fix-button.components-button.is-secondary.is-small {
border-color: rgba(96, 165, 250, 0.72);
box-shadow: none !important;
color: #bfdbfe;
flex-shrink: 0;
height: 24px;
min-width: 44px;
padding: 0 8px;
}
.wpaw-seo-fix-button.components-button.is-secondary.is-small:hover:not(
:disabled
),
.wpaw-seo-fix-button.components-button.is-secondary.is-small:focus:not(
:disabled
) {
border-color: #60a5fa;
color: #eff6ff;
}
.wpaw-seo-fix-button.components-button.is-secondary.is-small.is-fixing {
border-color: #fbbf24;
color: #fde68a;
}
.wpaw-meta-info > button.components-button.is-secondary.is-small {
outline: unset !important;
color: #fbbf24;
border: 1px solid #fbbf24;
@@ -3368,7 +3637,9 @@ input.wpaw-plan-section-check:checked::before {
border-radius: 4px;
font-size: 12px;
cursor: pointer;
transition: border-color 0.2s, background 0.2s;
transition:
border-color 0.2s,
background 0.2s;
}
.wpaw-fk-select {
@@ -3386,7 +3657,9 @@ input.wpaw-plan-section-check:checked::before {
padding: 6px 10px;
border-radius: 4px;
font-size: 12px;
transition: border-color 0.2s, background 0.2s;
transition:
border-color 0.2s,
background 0.2s;
}
.wpaw-fk-input:focus {
@@ -3411,7 +3684,9 @@ input.wpaw-plan-section-check:checked::before {
padding: 10px 12px;
border-radius: 6px;
font-size: 14px;
transition: border-color 0.2s, background 0.2s;
transition:
border-color 0.2s,
background 0.2s;
}
.wpaw-fk-custom-input:focus {
@@ -3460,7 +3735,9 @@ input.wpaw-plan-section-check:checked::before {
display: flex;
align-items: center;
justify-content: center;
transition: background 0.2s, color 0.2s;
transition:
background 0.2s,
color 0.2s;
}
.wpaw-fk-expand:hover,
@@ -3618,7 +3895,9 @@ input.wpaw-plan-section-check:checked::before {
font-size: 14px;
margin-bottom: 1rem;
box-sizing: border-box;
transition: border-color 0.2s, background 0.2s;
transition:
border-color 0.2s,
background 0.2s;
}
.wpaw-welcome-input:focus {
@@ -3919,7 +4198,6 @@ input.wpaw-plan-section-check:checked::before {
P2: TYPING ANIMATION
=========================== */
@keyframes wpaw-typewriter-cursor {
0%,
100% {
border-color: transparent;
@@ -3962,7 +4240,6 @@ input.wpaw-plan-section-check:checked::before {
}
@keyframes wpaw-typing-bounce {
0%,
60%,
100% {
@@ -4030,8 +4307,13 @@ input.wpaw-plan-section-check:checked::before {
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
.wpaw-suggestion-item {
@@ -4169,7 +4451,9 @@ input.wpaw-plan-section-check:checked::before {
max-width: 90vw;
background: #2d2d2d;
border-radius: 12px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.1);
box-shadow:
0 20px 60px rgba(0, 0, 0, 0.5),
0 0 0 1px rgba(255, 255, 255, 0.1);
overflow: hidden;
animation: wpaw-palette-slide-in 0.15s ease-out;
}
@@ -4550,7 +4834,6 @@ input.wpaw-plan-section-check:checked::before {
color: #f59e0b;
}
/* ===========================
AUDIT FIXES: Mode Indicator Badge
=========================== */
@@ -4567,10 +4850,20 @@ input.wpaw-plan-section-check:checked::before {
margin-bottom: 0.5em !important;
letter-spacing: normal !important;
}
.wpaw-response-content h1 {
font-size: 20px !important;
color: #e8ecf2 !important;
font-weight: bold;
margin-top: 1.5rem;
margin-bottom: 1rem;
}
.wpaw-response-content h2 {
font-size: 17px !important;
color: #e8ecf2 !important;
font-weight: bold;
margin-top: 1rem;
margin-bottom: 1rem;
}
.wpaw-response-content h4,
@@ -4580,6 +4873,17 @@ input.wpaw-plan-section-check:checked::before {
color: #d0d5dd !important;
}
.wpaw-response-content table {
border-collapse: collapse;
width: 100%;
}
.wpaw-response-content table th,
table td {
border: 1px solid #dce0e8 !important;
padding: 4px 6px;
}
.wpaw-mode-badge {
display: inline-flex;
align-items: center;
@@ -4763,7 +5067,7 @@ input.wpaw-plan-section-check:checked::before {
color: #dce0e8;
}
.wpaw-response-content>* {
.wpaw-response-content > * {
padding: 1rem;
}
@@ -4801,7 +5105,8 @@ input.wpaw-plan-section-check:checked::before {
.wpaw-config-summary-item {
color: #9aa5b4;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
font-family:
-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
margin-bottom: 4px;
font-size: 11.5px;
}

File diff suppressed because it is too large Load Diff