mop-agent 0.1.14 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,7 +5,7 @@ through MOP-FLOW. It stores project memory, performs semantic recall and
5
5
  consolidation, serves grounded chat, and can request approved actions from a
6
6
  linked FLOW node.
7
7
 
8
- > **Release status:** release candidate `mop-agent@0.1.14` contains the corrected VPS
8
+ > **Release status:** release candidate `mop-agent@0.1.15` contains the corrected VPS
9
9
  > installer, one-time Admin setup/login flow, and simplified shared application shell
10
10
  > with centered page titles and ChatGPT-inspired navigation.
11
11
  > The canonical installation command is exactly `npx mop-agent`.
@@ -19,6 +19,7 @@ export default function AssistantPage() {
19
19
  const [history, setHistory] = useState<SavedChat[]>([]);
20
20
  const [historyReady, setHistoryReady] = useState(false);
21
21
  const [activeChatId, setActiveChatId] = useState("");
22
+ const [historyCollapsed, setHistoryCollapsed] = useState(false);
22
23
  const endRef = useRef<HTMLDivElement>(null);
23
24
 
24
25
  useEffect(() => {
@@ -31,6 +32,7 @@ export default function AssistantPage() {
31
32
  try {
32
33
  const stored = JSON.parse(window.localStorage.getItem(CHAT_HISTORY_KEY) ?? "[]");
33
34
  if (Array.isArray(stored)) setHistory(stored.slice(0, 30));
35
+ setHistoryCollapsed(window.localStorage.getItem("mop-agent-history-collapsed") === "1");
34
36
  } catch {
35
37
  window.localStorage.removeItem(CHAT_HISTORY_KEY);
36
38
  } finally {
@@ -78,6 +80,13 @@ export default function AssistantPage() {
78
80
  if (activeChatId === id) startNewChat();
79
81
  }
80
82
 
83
+ function toggleHistory() {
84
+ setHistoryCollapsed((collapsed) => {
85
+ window.localStorage.setItem("mop-agent-history-collapsed", collapsed ? "0" : "1");
86
+ return !collapsed;
87
+ });
88
+ }
89
+
81
90
  async function send(prefill?: string) {
82
91
  const message = (prefill ?? input).trim();
83
92
  if (!message || busy) return;
@@ -124,7 +133,7 @@ export default function AssistantPage() {
124
133
  }
125
134
 
126
135
  return (
127
- <section className="mop-assistant-page">
136
+ <section className={`mop-assistant-page${historyCollapsed ? " is-history-collapsed" : ""}`}>
128
137
  <div className="mop-assistant-workspace">
129
138
  <div className="mop-assistant-conversation">
130
139
  {turns.length === 0 ? (
@@ -184,11 +193,20 @@ export default function AssistantPage() {
184
193
 
185
194
  <aside className="mop-chat-history" aria-label="Chat history">
186
195
  <div className="mop-chat-history-header">
187
- <div>
188
- <span>MEMORY LOG</span>
189
- <strong>Chat history</strong>
196
+ <strong>Chat history</strong>
197
+ <div className="mop-chat-history-actions">
198
+ <button
199
+ className="mop-chat-history-collapse"
200
+ type="button"
201
+ onClick={toggleHistory}
202
+ aria-label={historyCollapsed ? "Expand chat history" : "Collapse chat history"}
203
+ aria-expanded={!historyCollapsed}
204
+ title={historyCollapsed ? "Expand chat history" : "Collapse chat history"}
205
+ >
206
+ {historyCollapsed ? "‹" : "›"}
207
+ </button>
208
+ <button className="mop-chat-history-new" type="button" onClick={startNewChat} disabled={busy} title="Start a new chat">+</button>
190
209
  </div>
191
- <button type="button" onClick={startNewChat} disabled={busy} title="Start a new chat">+</button>
192
210
  </div>
193
211
  <div className="mop-chat-history-list">
194
212
  {history.length === 0 ? (
@@ -121,15 +121,22 @@ button {
121
121
  box-shadow: 0 2px 0 rgba(45, 74, 62, .28);
122
122
  }
123
123
 
124
+ .mop-app-brand-cell {
125
+ position: relative;
126
+ min-width: 0;
127
+ display: flex;
128
+ border-right: 1px solid rgba(254, 249, 225, .16);
129
+ }
130
+
124
131
  .mop-app-brand {
132
+ width: 100%;
125
133
  display: flex;
126
134
  align-items: center;
127
135
  gap: 9px;
128
136
  min-width: 0;
129
- padding: 7px 14px;
137
+ padding: 7px 46px 7px 14px;
130
138
  color: var(--mop-cream);
131
139
  text-decoration: none;
132
- border-right: 1px solid rgba(254, 249, 225, .16);
133
140
  }
134
141
 
135
142
  .mop-app-brand img {
@@ -148,6 +155,51 @@ button {
148
155
  white-space: nowrap;
149
156
  }
150
157
 
158
+ .mop-sidebar-collapse-toggle {
159
+ position: absolute;
160
+ top: 50%;
161
+ right: 9px;
162
+ z-index: 2;
163
+ width: 29px;
164
+ height: 34px;
165
+ display: grid;
166
+ place-items: center;
167
+ padding: 0;
168
+ transform: translateY(-50%);
169
+ border: 1px solid rgba(254, 249, 225, .25);
170
+ background: rgba(254, 249, 225, .08);
171
+ color: var(--mop-cream);
172
+ font-size: 19px;
173
+ cursor: pointer;
174
+ }
175
+
176
+ .mop-sidebar-collapse-toggle:hover:not(:disabled) { transform: translate(-1px, calc(-50% - 1px)); }
177
+ .mop-sidebar-collapse-toggle:active:not(:disabled) { transform: translate(1px, calc(-50% + 1px)); }
178
+
179
+ .mop-app-frame,
180
+ .mop-app-topbar { transition: grid-template-columns 140ms steps(4, end); }
181
+
182
+ .mop-app-frame.is-sidebar-collapsed { grid-template-columns: 74px minmax(0, 1fr); }
183
+ .mop-app-frame.is-sidebar-collapsed .mop-app-topbar { grid-template-columns: 74px minmax(0, 1fr); }
184
+ .mop-app-frame.is-sidebar-collapsed .mop-app-brand { justify-content: center; padding: 7px; }
185
+ .mop-app-frame.is-sidebar-collapsed .mop-app-brand img { width: 47px; height: 47px; }
186
+ .mop-app-frame.is-sidebar-collapsed .mop-app-brand span,
187
+ .mop-app-frame.is-sidebar-collapsed .mop-nav-section > p,
188
+ .mop-app-frame.is-sidebar-collapsed .mop-sidebar-primary a > span:not(.mop-nav-icon),
189
+ .mop-app-frame.is-sidebar-collapsed .mop-nav-section a > span:not(.mop-nav-icon),
190
+ .mop-app-frame.is-sidebar-collapsed .mop-nav-section button > span:not(.mop-nav-icon),
191
+ .mop-app-frame.is-sidebar-collapsed .mop-account-copy,
192
+ .mop-app-frame.is-sidebar-collapsed .mop-account-card > span:last-child,
193
+ .mop-app-frame.is-sidebar-collapsed .mop-back-workspace-btn > span { display: none; }
194
+ .mop-app-frame.is-sidebar-collapsed .mop-sidebar-collapse-toggle { right: -14px; }
195
+ .mop-app-frame.is-sidebar-collapsed .mop-app-sidebar { padding-inline: 9px; }
196
+ .mop-app-frame.is-sidebar-collapsed .mop-sidebar-primary a,
197
+ .mop-app-frame.is-sidebar-collapsed .mop-nav-section a,
198
+ .mop-app-frame.is-sidebar-collapsed .mop-nav-section button,
199
+ .mop-app-frame.is-sidebar-collapsed .mop-account-card { justify-content: center; padding-inline: 5px; }
200
+ .mop-app-frame.is-sidebar-collapsed .mop-nav-icon { width: auto; }
201
+ .mop-app-frame.is-sidebar-collapsed .mop-back-workspace-btn::before { content: "←"; }
202
+
151
203
  .mop-app-topbar-main {
152
204
  position: relative;
153
205
  min-width: 0;
@@ -371,8 +423,11 @@ button {
371
423
  display: grid;
372
424
  grid-template-columns: minmax(0, 1fr) 290px;
373
425
  overflow: hidden;
426
+ transition: grid-template-columns 140ms steps(4, end);
374
427
  }
375
428
 
429
+ .mop-assistant-page.is-history-collapsed { grid-template-columns: minmax(0, 1fr) 52px; }
430
+
376
431
  .mop-assistant-workspace {
377
432
  min-width: 0;
378
433
  min-height: 0;
@@ -425,15 +480,8 @@ button {
425
480
  border-bottom: 1px solid rgba(45, 74, 62, .24);
426
481
  }
427
482
 
428
- .mop-chat-history-header > div { display: grid; gap: 3px; }
429
- .mop-chat-history-header span {
430
- color: var(--mop-red);
431
- font-family: "SFMono-Regular", Consolas, monospace;
432
- font-size: 8px;
433
- font-weight: 900;
434
- letter-spacing: .16em;
435
- }
436
483
  .mop-chat-history-header strong { font-family: "SFMono-Regular", Consolas, monospace; font-size: 15px; }
484
+ .mop-chat-history-actions { display: flex; gap: 6px; }
437
485
  .mop-chat-history-header button {
438
486
  width: 34px;
439
487
  height: 34px;
@@ -443,6 +491,19 @@ button {
443
491
  font-size: 20px;
444
492
  cursor: pointer;
445
493
  }
494
+ .mop-chat-history-collapse { background: var(--mop-green) !important; }
495
+ .mop-chat-history-new { background: var(--mop-red) !important; }
496
+
497
+ .mop-assistant-page.is-history-collapsed .mop-chat-history { padding: 12px 8px; }
498
+ .mop-assistant-page.is-history-collapsed .mop-chat-history-header {
499
+ justify-content: center;
500
+ padding: 0 0 12px;
501
+ border-bottom: 0;
502
+ }
503
+ .mop-assistant-page.is-history-collapsed .mop-chat-history-header > strong,
504
+ .mop-assistant-page.is-history-collapsed .mop-chat-history-new,
505
+ .mop-assistant-page.is-history-collapsed .mop-chat-history-list { display: none; }
506
+ .mop-assistant-page.is-history-collapsed .mop-chat-history-actions { display: block; }
446
507
 
447
508
  .mop-chat-history-list {
448
509
  min-height: 0;
@@ -541,7 +602,10 @@ button {
541
602
  grid-template-rows: 62px minmax(0, 1fr);
542
603
  grid-template-areas: "topbar" "main";
543
604
  }
605
+ .mop-app-frame.is-sidebar-collapsed { grid-template-columns: 1fr; }
544
606
  .mop-app-topbar { grid-template-columns: 66px minmax(0, 1fr); }
607
+ .mop-app-frame.is-sidebar-collapsed .mop-app-topbar { grid-template-columns: 66px minmax(0, 1fr); }
608
+ .mop-sidebar-collapse-toggle { display: none; }
545
609
  .mop-app-brand { justify-content: center; padding: 5px; }
546
610
  .mop-app-brand img { width: 49px; height: 49px; }
547
611
  .mop-app-brand span { display: none; }
@@ -559,6 +623,18 @@ button {
559
623
  transition: transform 160ms steps(4, end);
560
624
  }
561
625
  .mop-app-sidebar.is-open { transform: translateX(0); }
626
+ .mop-app-frame.is-sidebar-collapsed .mop-nav-section > p { display: block; }
627
+ .mop-app-frame.is-sidebar-collapsed .mop-sidebar-primary a > span:not(.mop-nav-icon),
628
+ .mop-app-frame.is-sidebar-collapsed .mop-nav-section a > span:not(.mop-nav-icon),
629
+ .mop-app-frame.is-sidebar-collapsed .mop-nav-section button > span:not(.mop-nav-icon),
630
+ .mop-app-frame.is-sidebar-collapsed .mop-back-workspace-btn > span { display: inline; }
631
+ .mop-app-frame.is-sidebar-collapsed .mop-account-copy { display: grid; }
632
+ .mop-app-frame.is-sidebar-collapsed .mop-account-card > span:last-child { display: inline; }
633
+ .mop-app-frame.is-sidebar-collapsed .mop-sidebar-primary a,
634
+ .mop-app-frame.is-sidebar-collapsed .mop-nav-section a,
635
+ .mop-app-frame.is-sidebar-collapsed .mop-nav-section button,
636
+ .mop-app-frame.is-sidebar-collapsed .mop-account-card { justify-content: flex-start; padding-inline: 11px; }
637
+ .mop-app-frame.is-sidebar-collapsed .mop-back-workspace-btn::before { content: none; }
562
638
  .mop-sidebar-scrim {
563
639
  display: block;
564
640
  position: fixed;
@@ -568,7 +644,8 @@ button {
568
644
  background: rgba(20, 34, 29, .56);
569
645
  }
570
646
  .mop-app-main { min-height: calc(100vh - 62px); }
571
- .mop-assistant-page { height: calc(100vh - 62px); min-height: 520px; grid-template-columns: minmax(0, 1fr); }
647
+ .mop-assistant-page,
648
+ .mop-assistant-page.is-history-collapsed { height: calc(100vh - 62px); min-height: 520px; grid-template-columns: minmax(0, 1fr); }
572
649
  .mop-chat-history { display: none; }
573
650
  .mop-assistant-conversation { padding: 0 16px; }
574
651
  .mop-assistant-composer-wrap { padding: 26px 12px 12px; }
@@ -40,6 +40,7 @@ function pageTitle(pathname: string): string {
40
40
  export function AppShell({ viewer, children }: { viewer: AppViewer; children: ReactNode }) {
41
41
  const pathname = usePathname();
42
42
  const [menuOpen, setMenuOpen] = useState(false);
43
+ const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
43
44
  const [projects, setProjects] = useState<Project[]>([]);
44
45
  const [settingsSection, setSettingsSection] = useState<"providers" | "users">("providers");
45
46
  const isAdmin = viewer.role === "owner";
@@ -54,6 +55,7 @@ export function AppShell({ viewer, children }: { viewer: AppViewer; children: Re
54
55
 
55
56
  const requested = new URLSearchParams(window.location.search).get("section");
56
57
  if (requested === "users") setSettingsSection("users");
58
+ setSidebarCollapsed(window.localStorage.getItem("mop-agent-sidebar-collapsed") === "1");
57
59
  }, []);
58
60
 
59
61
  async function logout() {
@@ -66,14 +68,33 @@ export function AppShell({ viewer, children }: { viewer: AppViewer; children: Re
66
68
  window.history.replaceState(null, "", section === "providers" ? "/settings" : "/settings?section=users");
67
69
  }
68
70
 
71
+ function toggleSidebar() {
72
+ setSidebarCollapsed((collapsed) => {
73
+ window.localStorage.setItem("mop-agent-sidebar-collapsed", collapsed ? "0" : "1");
74
+ return !collapsed;
75
+ });
76
+ }
77
+
69
78
  return (
70
79
  <MemoryCoreContext.Provider value={{ projects, settingsSection, setSettingsSection }}>
71
- <div className="mop-app-frame">
80
+ <div className={`mop-app-frame${sidebarCollapsed ? " is-sidebar-collapsed" : ""}`}>
72
81
  <header className="mop-app-topbar">
73
- <a className="mop-app-brand" href="/assistant" aria-label="MOP-AGENT home">
74
- <img src="/icon.svg" alt="" />
75
- <span>MOP-AGENT</span>
76
- </a>
82
+ <div className="mop-app-brand-cell">
83
+ <a className="mop-app-brand" href="/assistant" aria-label="MOP-AGENT home">
84
+ <img src="/icon.svg" alt="" />
85
+ <span>MOP-AGENT</span>
86
+ </a>
87
+ <button
88
+ className="mop-sidebar-collapse-toggle"
89
+ type="button"
90
+ aria-label={sidebarCollapsed ? "Expand sidebar" : "Collapse sidebar"}
91
+ aria-expanded={!sidebarCollapsed}
92
+ title={sidebarCollapsed ? "Expand sidebar" : "Collapse sidebar"}
93
+ onClick={toggleSidebar}
94
+ >
95
+ {sidebarCollapsed ? "›" : "‹"}
96
+ </button>
97
+ </div>
77
98
  <div className="mop-app-topbar-main">
78
99
  <button
79
100
  className="mop-menu-toggle"
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "mop-agent",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "mop-agent",
9
- "version": "0.1.14",
9
+ "version": "0.1.15",
10
10
  "license": "UNLICENSED",
11
11
  "workspaces": [
12
12
  "packages/*",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mop-agent",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "description": "Self-hosted AI assistant with persistent cross-project memory, installed with npx mop-agent.",
5
5
  "author": "BURHANDEV ENTERPRISE",
6
6
  "license": "UNLICENSED",