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 +1 -1
- package/apps/web/app/assistant/page.tsx +23 -5
- package/apps/web/app/globals.css +88 -11
- package/apps/web/components/AppShell.tsx +26 -5
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
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.
|
|
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=
|
|
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
|
-
<
|
|
188
|
-
|
|
189
|
-
<
|
|
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 ? (
|
package/apps/web/app/globals.css
CHANGED
|
@@ -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
|
|
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=
|
|
80
|
+
<div className={`mop-app-frame${sidebarCollapsed ? " is-sidebar-collapsed" : ""}`}>
|
|
72
81
|
<header className="mop-app-topbar">
|
|
73
|
-
<
|
|
74
|
-
<
|
|
75
|
-
|
|
76
|
-
|
|
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"
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mop-agent",
|
|
3
|
-
"version": "0.1.
|
|
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.
|
|
9
|
+
"version": "0.1.15",
|
|
10
10
|
"license": "UNLICENSED",
|
|
11
11
|
"workspaces": [
|
|
12
12
|
"packages/*",
|
package/package.json
CHANGED