Initial commit: NexusOS project + desktop theme baseline

Captures the known-good state after theme consolidation and
consistency reconciliation:
- NexusOS GTK/xfwm4/icon theme assets (assets/themes, management/Mint-Y-Nexus)
- Tightened right-click menus, visible separators, no menu icons
- assets/themes/install-theme.sh: idempotent restore of all wiring
  (symlinks, xfconf xsettings+xfwm4, GTK 3/4 settings.ini)
- .gitignore excludes venv/ollama/models/runtime/db

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
jon
2026-05-18 13:39:48 -05:00
commit b0aa0438af
1264 changed files with 19255 additions and 0 deletions
+243
View File
@@ -0,0 +1,243 @@
import { useEffect, useState, useCallback } from "react";
import { API_BASE } from "./config";
const DEFAULT_SECTIONS = ["Instructions", "Identity", "Career", "Projects", "Preferences"];
function groupBySection(items) {
const map = {};
for (const item of items) {
const sec = item.section || "General";
if (!map[sec]) map[sec] = [];
map[sec].push(item);
}
return map;
}
export function Memory() {
const [items, setItems] = useState([]);
const [editing, setEditing] = useState(null); // { id, section, text } or null
const [adding, setAdding] = useState(null); // { section } for inline new-item form
const [newSection, setNewSection] = useState("");
const [showNewSection, setShowNewSection] = useState(false);
const [message, setMessage] = useState("");
const loadItems = useCallback(async () => {
try {
const res = await fetch(`${API_BASE}/memory`);
const data = res.ok ? await res.json() : { items: [] };
setItems(data.items || []);
} catch {
setItems([]);
}
}, []);
useEffect(() => { loadItems(); }, [loadItems]);
const flash = (msg) => { setMessage(msg); setTimeout(() => setMessage(""), 3000); };
const saveNew = async (section, text) => {
if (!text.trim()) return;
const res = await fetch(`${API_BASE}/memory`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ section, text: text.trim() }),
});
if (res.ok) { loadItems(); setAdding(null); flash("Saved."); }
else flash("Save failed.");
};
const saveEdit = async (id, section, text) => {
if (!text.trim()) return;
const res = await fetch(`${API_BASE}/memory/${id}`, {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ section, text: text.trim() }),
});
if (res.ok) { loadItems(); setEditing(null); flash("Updated."); }
else flash("Update failed.");
};
const deleteItem = async (id) => {
if (!window.confirm("Delete this item?")) return;
const res = await fetch(`${API_BASE}/memory/${id}`, { method: "DELETE" });
if (res.ok) { loadItems(); flash("Deleted."); }
else flash("Delete failed.");
};
const addSection = () => {
const sec = newSection.trim();
if (!sec) return;
// Create a placeholder item to establish the section, then let user fill it
setAdding({ section: sec });
setNewSection("");
setShowNewSection(false);
};
const grouped = groupBySection(items);
const sections = Object.keys(grouped);
const inputStyle = {
background: "#1a1a1a",
color: "#eee",
border: "1px solid #444",
borderRadius: "6px",
padding: "0.4rem 0.6rem",
fontSize: "0.9rem",
width: "100%",
boxSizing: "border-box",
};
const btnStyle = (color = "#007acc") => ({
padding: "0.3rem 0.7rem",
background: color,
color: "#fff",
border: "none",
borderRadius: "6px",
cursor: "pointer",
fontSize: "0.8rem",
});
return (
<div style={{ flexGrow: 1, maxWidth: "860px" }}>
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "1.25rem" }}>
<div>
<h2 style={{ margin: 0, fontSize: "1.1rem" }}>Memory</h2>
<p style={{ margin: "0.25rem 0 0", color: "#888", fontSize: "0.85rem" }}>
Facts injected into every conversation. Format mirrors your claude.md.
</p>
</div>
<button onClick={() => setShowNewSection(s => !s)} style={btnStyle()}>
+ New Section
</button>
</div>
{showNewSection && (
<div style={{ display: "flex", gap: "0.5rem", marginBottom: "1.25rem" }}>
<input
autoFocus
type="text"
placeholder="Section name (e.g. Health, Finance)"
value={newSection}
onChange={e => setNewSection(e.target.value)}
onKeyDown={e => { if (e.key === "Enter") addSection(); if (e.key === "Escape") setShowNewSection(false); }}
style={{ ...inputStyle, maxWidth: "320px" }}
/>
<button onClick={addSection} style={btnStyle()}>Add</button>
<button onClick={() => setShowNewSection(false)} style={btnStyle("#444")}>Cancel</button>
</div>
)}
{sections.length === 0 && !adding && (
<div style={{ color: "#666", fontSize: "0.9rem", marginTop: "2rem" }}>
No memory yet. Add a section to get started.
</div>
)}
{/* Render sections in claude.md style */}
{[...sections, ...(adding && !sections.includes(adding.section) ? [adding.section] : [])].map(section => (
<div key={section} style={{ marginBottom: "2rem" }}>
{/* ## Section Header */}
<div style={{ display: "flex", alignItems: "center", gap: "0.75rem", marginBottom: "0.5rem" }}>
<h3 style={{ margin: 0, fontSize: "1rem", color: "#4db8ff" }}>## {section}</h3>
<button
onClick={() => setAdding({ section })}
style={{ ...btnStyle("#2a3a2a"), border: "1px solid #3a5a3a", color: "#7dcc7d", fontSize: "0.75rem" }}
>
+ Add item
</button>
</div>
{/* Bullet items */}
<div style={{ paddingLeft: "1rem", borderLeft: "2px solid #222" }}>
{(grouped[section] || []).map(item => (
<div key={item.id} style={{ marginBottom: "0.4rem" }}>
{editing?.id === item.id ? (
<EditRow
initial={editing.text}
onSave={text => saveEdit(item.id, section, text)}
onCancel={() => setEditing(null)}
inputStyle={inputStyle}
btnStyle={btnStyle}
/>
) : (
<div style={{ display: "flex", alignItems: "flex-start", gap: "0.5rem", group: true }}>
<span style={{ color: "#aaa", marginTop: "0.1rem", flexShrink: 0 }}>-</span>
<span style={{ color: "#ddd", fontSize: "0.9rem", flexGrow: 1 }}>{item.text}</span>
<div style={{ display: "flex", gap: "0.3rem", flexShrink: 0, opacity: 0.4 }}
onMouseEnter={e => e.currentTarget.style.opacity = 1}
onMouseLeave={e => e.currentTarget.style.opacity = 0.4}
>
<button
onClick={() => setEditing({ id: item.id, section, text: item.text })}
style={{ ...btnStyle("#333"), fontSize: "0.72rem", padding: "0.2rem 0.5rem" }}
>edit</button>
<button
onClick={() => deleteItem(item.id)}
style={{ ...btnStyle("#5a1a1a"), fontSize: "0.72rem", padding: "0.2rem 0.5rem" }}
>del</button>
</div>
</div>
)}
</div>
))}
{/* Inline add form */}
{adding?.section === section && (
<AddRow
onSave={text => saveNew(section, text)}
onCancel={() => setAdding(null)}
inputStyle={inputStyle}
btnStyle={btnStyle}
/>
)}
</div>
</div>
))}
{message && (
<div style={{ position: "fixed", bottom: "1.5rem", right: "1.5rem", background: "#1a2e1a", border: "1px solid #3a5a3a", color: "#7dcc7d", padding: "0.6rem 1rem", borderRadius: "8px", fontSize: "0.85rem" }}>
{message}
</div>
)}
</div>
);
}
function AddRow({ onSave, onCancel, inputStyle, btnStyle }) {
const [text, setText] = useState("");
return (
<div style={{ display: "flex", gap: "0.5rem", alignItems: "center", marginTop: "0.4rem" }}>
<span style={{ color: "#555", flexShrink: 0 }}>-</span>
<input
autoFocus
type="text"
placeholder="New item..."
value={text}
onChange={e => setText(e.target.value)}
onKeyDown={e => { if (e.key === "Enter") onSave(text); if (e.key === "Escape") onCancel(); }}
style={{ ...inputStyle }}
/>
<button onClick={() => onSave(text)} style={btnStyle()}>Save</button>
<button onClick={onCancel} style={btnStyle("#444")}></button>
</div>
);
}
function EditRow({ initial, onSave, onCancel, inputStyle, btnStyle }) {
const [text, setText] = useState(initial);
return (
<div style={{ display: "flex", gap: "0.5rem", alignItems: "center" }}>
<span style={{ color: "#555", flexShrink: 0 }}>-</span>
<input
autoFocus
type="text"
value={text}
onChange={e => setText(e.target.value)}
onKeyDown={e => { if (e.key === "Enter") onSave(text); if (e.key === "Escape") onCancel(); }}
style={{ ...inputStyle }}
/>
<button onClick={() => onSave(text)} style={btnStyle()}>Save</button>
<button onClick={onCancel} style={btnStyle("#444")}></button>
</div>
);
}