@saadnvd1/agent-os 0.3.608 → 0.3.610
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/components/Chat/composer/useCoarsePointer.ts +2 -14
- package/components/SessionList/OrchestratorPinRow.tsx +3 -3
- package/components/SessionList/RowMenuParts.tsx +90 -0
- package/components/SessionList/RowShell.tsx +6 -2
- package/components/SessionList/SessionRowMenu.tsx +241 -377
- package/components/ui/context-menu.tsx +4 -2
- package/components/ui/dropdown-menu.tsx +5 -2
- package/components/ui/menu-fit.test.ts +36 -0
- package/hooks/useCompactMenu.ts +9 -0
- package/hooks/useMediaQuery.ts +20 -0
- package/lib/hosts/remote-menu.ts +4 -0
- package/lib/load/alert.ts +5 -0
- package/lib/load/attribute.ts +217 -0
- package/lib/load/monitor.ts +32 -39
- package/lib/load/usage.ts +34 -25
- package/lib/sidebar/row-menu.ts +168 -0
- package/package.json +1 -1
|
@@ -1,20 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
const QUERY = "(pointer: coarse)";
|
|
6
|
-
|
|
7
|
-
function subscribe(listener: () => void) {
|
|
8
|
-
const mq = window.matchMedia(QUERY);
|
|
9
|
-
mq.addEventListener("change", listener);
|
|
10
|
-
return () => mq.removeEventListener("change", listener);
|
|
11
|
-
}
|
|
3
|
+
import { useMediaQuery } from "@/hooks/useMediaQuery";
|
|
12
4
|
|
|
13
5
|
// A touch screen with no keyboard to speak of: taps, not shortcuts.
|
|
14
6
|
export function useCoarsePointer(): boolean {
|
|
15
|
-
return
|
|
16
|
-
subscribe,
|
|
17
|
-
() => window.matchMedia(QUERY).matches,
|
|
18
|
-
() => false
|
|
19
|
-
);
|
|
7
|
+
return useMediaQuery("(pointer: coarse)");
|
|
20
8
|
}
|
|
@@ -14,7 +14,7 @@ import { cn } from "@/lib/utils";
|
|
|
14
14
|
import { orchestratorOpenActions } from "@/stores/orchestratorOpen";
|
|
15
15
|
import { useRowContext } from "./RowContext";
|
|
16
16
|
import { SessionRowMenu } from "./SessionRowMenu";
|
|
17
|
-
import { ActiveTick } from "./RowShell";
|
|
17
|
+
import { ActiveTick, ROW_MENU_CONTENT } from "./RowShell";
|
|
18
18
|
import { RowRename, UnreadDot } from "./RowParts";
|
|
19
19
|
import { QuickChangeRow } from "./QuickChangeRow";
|
|
20
20
|
import { NestRail } from "./RowParts";
|
|
@@ -158,7 +158,7 @@ export const OrchestratorPinRow = memo(function OrchestratorPinRow({
|
|
|
158
158
|
</DM.DropdownMenuTrigger>
|
|
159
159
|
<DM.DropdownMenuContent
|
|
160
160
|
align="end"
|
|
161
|
-
className=
|
|
161
|
+
className={ROW_MENU_CONTENT}
|
|
162
162
|
onClick={(e) => e.stopPropagation()}
|
|
163
163
|
>
|
|
164
164
|
{menu("dropdown")}
|
|
@@ -171,7 +171,7 @@ export const OrchestratorPinRow = memo(function OrchestratorPinRow({
|
|
|
171
171
|
<>
|
|
172
172
|
<CM.ContextMenu>
|
|
173
173
|
<CM.ContextMenuTrigger asChild>{content}</CM.ContextMenuTrigger>
|
|
174
|
-
<CM.ContextMenuContent className=
|
|
174
|
+
<CM.ContextMenuContent className={ROW_MENU_CONTENT}>
|
|
175
175
|
{menu("context")}
|
|
176
176
|
</CM.ContextMenuContent>
|
|
177
177
|
</CM.ContextMenu>
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useState, type ComponentProps, type ElementType } from "react";
|
|
4
|
+
import { ChevronDown } from "lucide-react";
|
|
5
|
+
import * as DM from "@/components/ui/dropdown-menu";
|
|
6
|
+
import * as CM from "@/components/ui/context-menu";
|
|
7
|
+
import { useCompactMenu } from "@/hooks/useCompactMenu";
|
|
8
|
+
import { cn } from "@/lib/utils";
|
|
9
|
+
|
|
10
|
+
export const PARTS = {
|
|
11
|
+
dropdown: {
|
|
12
|
+
Item: DM.DropdownMenuItem,
|
|
13
|
+
Separator: DM.DropdownMenuSeparator,
|
|
14
|
+
Sub: DM.DropdownMenuSub,
|
|
15
|
+
SubTrigger: DM.DropdownMenuSubTrigger,
|
|
16
|
+
SubContent: DM.DropdownMenuSubContent,
|
|
17
|
+
},
|
|
18
|
+
context: {
|
|
19
|
+
Item: CM.ContextMenuItem,
|
|
20
|
+
Separator: CM.ContextMenuSeparator,
|
|
21
|
+
Sub: CM.ContextMenuSub,
|
|
22
|
+
SubTrigger: CM.ContextMenuSubTrigger,
|
|
23
|
+
SubContent: CM.ContextMenuSubContent,
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export type MenuKind = keyof typeof PARTS;
|
|
28
|
+
|
|
29
|
+
export const icon = "mr-2 h-3.5 w-3.5";
|
|
30
|
+
|
|
31
|
+
// An item that is a 44px target on a phone.
|
|
32
|
+
export function MenuItem({
|
|
33
|
+
kind,
|
|
34
|
+
className,
|
|
35
|
+
...props
|
|
36
|
+
}: { kind: MenuKind } & ComponentProps<typeof DM.DropdownMenuItem>) {
|
|
37
|
+
const compact = useCompactMenu();
|
|
38
|
+
const Item = PARTS[kind].Item as typeof DM.DropdownMenuItem;
|
|
39
|
+
return <Item className={cn(compact && "min-h-11", className)} {...props} />;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// A submenu on a desktop; on a phone or touch screen, a row that opens its
|
|
43
|
+
// items in place (a flyout can't be held open by a finger, and the list
|
|
44
|
+
// beneath it keeps scrolling as one).
|
|
45
|
+
export function Expander({
|
|
46
|
+
kind,
|
|
47
|
+
icon: Icon,
|
|
48
|
+
label,
|
|
49
|
+
children,
|
|
50
|
+
}: {
|
|
51
|
+
kind: MenuKind;
|
|
52
|
+
icon: ElementType;
|
|
53
|
+
label: string;
|
|
54
|
+
children: React.ReactNode;
|
|
55
|
+
}) {
|
|
56
|
+
const compact = useCompactMenu();
|
|
57
|
+
const [open, setOpen] = useState(false);
|
|
58
|
+
const { Sub, SubTrigger, SubContent } = PARTS[kind];
|
|
59
|
+
if (!compact)
|
|
60
|
+
return (
|
|
61
|
+
<Sub>
|
|
62
|
+
<SubTrigger>
|
|
63
|
+
<Icon className={icon} />
|
|
64
|
+
{label}
|
|
65
|
+
</SubTrigger>
|
|
66
|
+
<SubContent>{children}</SubContent>
|
|
67
|
+
</Sub>
|
|
68
|
+
);
|
|
69
|
+
return (
|
|
70
|
+
<>
|
|
71
|
+
<MenuItem
|
|
72
|
+
kind={kind}
|
|
73
|
+
aria-expanded={open}
|
|
74
|
+
onSelect={(e) => {
|
|
75
|
+
e.preventDefault();
|
|
76
|
+
setOpen((o) => !o);
|
|
77
|
+
}}
|
|
78
|
+
>
|
|
79
|
+
<Icon className={icon} />
|
|
80
|
+
{label}
|
|
81
|
+
<ChevronDown
|
|
82
|
+
className={cn("ml-auto transition-transform", open && "rotate-180")}
|
|
83
|
+
/>
|
|
84
|
+
</MenuItem>
|
|
85
|
+
{open && (
|
|
86
|
+
<div className="border-border ml-4 border-l pl-1">{children}</div>
|
|
87
|
+
)}
|
|
88
|
+
</>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
@@ -18,6 +18,10 @@ export function ActiveTick() {
|
|
|
18
18
|
);
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
// A phone gets the full width, a desktop a fixed column; either scrolls when
|
|
22
|
+
// the window is short (the menu primitives cap their height).
|
|
23
|
+
export const ROW_MENU_CONTENT = "w-56 max-md:w-[calc(100vw-1rem)]";
|
|
24
|
+
|
|
21
25
|
export type RowMenuKind = "dropdown" | "context";
|
|
22
26
|
|
|
23
27
|
// Every sidebar row's frame: a leading mark, title over subtitle, what's on
|
|
@@ -109,7 +113,7 @@ export function RowShell({
|
|
|
109
113
|
</DM.DropdownMenuTrigger>
|
|
110
114
|
<DM.DropdownMenuContent
|
|
111
115
|
align="end"
|
|
112
|
-
className=
|
|
116
|
+
className={ROW_MENU_CONTENT}
|
|
113
117
|
onClick={(e) => e.stopPropagation()}
|
|
114
118
|
>
|
|
115
119
|
{menu("dropdown")}
|
|
@@ -122,7 +126,7 @@ export function RowShell({
|
|
|
122
126
|
return (
|
|
123
127
|
<CM.ContextMenu>
|
|
124
128
|
<CM.ContextMenuTrigger asChild>{content}</CM.ContextMenuTrigger>
|
|
125
|
-
<CM.ContextMenuContent className=
|
|
129
|
+
<CM.ContextMenuContent className={ROW_MENU_CONTENT}>
|
|
126
130
|
{menu("context")}
|
|
127
131
|
</CM.ContextMenuContent>
|
|
128
132
|
</CM.ContextMenu>
|