pi-orchestrator-config 4.1.5

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.
Files changed (175) hide show
  1. package/README.md +808 -0
  2. package/agents/api-documenter.md +32 -0
  3. package/agents/bash-expert.md +53 -0
  4. package/agents/code-reviewer-docs.md +145 -0
  5. package/agents/code-reviewer-guidelines.md +97 -0
  6. package/agents/code-reviewer-quality.md +142 -0
  7. package/agents/code-reviewer-security.md +107 -0
  8. package/agents/code-reviewer-spec.md +164 -0
  9. package/agents/debugger.md +63 -0
  10. package/agents/docker-expert.md +40 -0
  11. package/agents/docs-fetcher.md +48 -0
  12. package/agents/git-expert.md +63 -0
  13. package/agents/github-expert.md +83 -0
  14. package/agents/go-expert.md +62 -0
  15. package/agents/issue-reviewer-feasibility.md +60 -0
  16. package/agents/issue-reviewer-scope.md +63 -0
  17. package/agents/issue-reviewer-spec.md +77 -0
  18. package/agents/java-expert.md +31 -0
  19. package/agents/jenkins-expert.md +38 -0
  20. package/agents/kubernetes-expert.md +40 -0
  21. package/agents/planner.md +42 -0
  22. package/agents/python-expert.md +61 -0
  23. package/agents/reviewer.md +26 -0
  24. package/agents/scout.md +40 -0
  25. package/agents/security-auditor.md +254 -0
  26. package/agents/technical-documentation-writer.md +37 -0
  27. package/agents/test-automator.md +55 -0
  28. package/agents/test-runner.md +47 -0
  29. package/agents/ts-expert.md +23 -0
  30. package/agents/worker.md +30 -0
  31. package/extensions/acpx-provider/index.ts +104 -0
  32. package/extensions/acpx-provider/load-runtime.ts +99 -0
  33. package/extensions/acpx-provider/runtime-models.ts +40 -0
  34. package/extensions/cli-provider/agents/claude.ts +128 -0
  35. package/extensions/cli-provider/agents/cursor.ts +84 -0
  36. package/extensions/cli-provider/agents/gemini.ts +100 -0
  37. package/extensions/cli-provider/discover.ts +77 -0
  38. package/extensions/cli-provider/index.ts +57 -0
  39. package/extensions/cli-provider/parsers.ts +304 -0
  40. package/extensions/cli-provider/providers.ts +58 -0
  41. package/extensions/cli-provider/runner.ts +225 -0
  42. package/extensions/cli-provider/runtime-models.ts +32 -0
  43. package/extensions/cli-provider/session-reaper.ts +122 -0
  44. package/extensions/cli-provider/sessions.ts +533 -0
  45. package/extensions/cli-provider/shared/discover-cache.ts +235 -0
  46. package/extensions/cli-provider/types.ts +48 -0
  47. package/extensions/coms/coms-net-server.ts +1642 -0
  48. package/extensions/coms/coms-net-wrapper.ts +521 -0
  49. package/extensions/coms/coms-net.ts +1589 -0
  50. package/extensions/coms/coms-p2p.ts +1879 -0
  51. package/extensions/coms/coms-shared.ts +510 -0
  52. package/extensions/coms/coms-wrapper.ts +138 -0
  53. package/extensions/coms/index.ts +20 -0
  54. package/extensions/coms/themeMap.ts +147 -0
  55. package/extensions/image-gen/image-gen.ts +332 -0
  56. package/extensions/image-gen/index.ts +14 -0
  57. package/extensions/orchestrator/agents.ts +134 -0
  58. package/extensions/orchestrator/ask-user.ts +293 -0
  59. package/extensions/orchestrator/async-agents.ts +1037 -0
  60. package/extensions/orchestrator/async-capability.ts +129 -0
  61. package/extensions/orchestrator/async-runner.ts +324 -0
  62. package/extensions/orchestrator/async-status-parse.ts +31 -0
  63. package/extensions/orchestrator/async-status-ui.ts +201 -0
  64. package/extensions/orchestrator/async-wait.ts +36 -0
  65. package/extensions/orchestrator/btw.ts +210 -0
  66. package/extensions/orchestrator/cron-status-format.ts +126 -0
  67. package/extensions/orchestrator/cron-status-ui.ts +132 -0
  68. package/extensions/orchestrator/cron.ts +730 -0
  69. package/extensions/orchestrator/dreaming.ts +355 -0
  70. package/extensions/orchestrator/enforcement-helpers.ts +530 -0
  71. package/extensions/orchestrator/enforcement-rules.ts +329 -0
  72. package/extensions/orchestrator/enforcement.ts +828 -0
  73. package/extensions/orchestrator/extended-autocomplete.ts +593 -0
  74. package/extensions/orchestrator/git-helpers.ts +420 -0
  75. package/extensions/orchestrator/github-autocomplete.ts +250 -0
  76. package/extensions/orchestrator/icons.ts +17 -0
  77. package/extensions/orchestrator/index.ts +100 -0
  78. package/extensions/orchestrator/memory-embeddings.ts +281 -0
  79. package/extensions/orchestrator/memory-promotion.ts +449 -0
  80. package/extensions/orchestrator/memory-provenance.ts +80 -0
  81. package/extensions/orchestrator/memory-query-class.ts +90 -0
  82. package/extensions/orchestrator/memory-scoring.ts +434 -0
  83. package/extensions/orchestrator/memory-tools.ts +883 -0
  84. package/extensions/orchestrator/memory-tree.ts +212 -0
  85. package/extensions/orchestrator/nvim.ts +169 -0
  86. package/extensions/orchestrator/overlay-dashboard-utils.ts +25 -0
  87. package/extensions/orchestrator/overlay-dashboard.ts +512 -0
  88. package/extensions/orchestrator/pi-config-review-state.ts +303 -0
  89. package/extensions/orchestrator/preference-extractor.ts +106 -0
  90. package/extensions/orchestrator/project-settings.ts +468 -0
  91. package/extensions/orchestrator/promotion-queue.ts +311 -0
  92. package/extensions/orchestrator/resolve-agent-model.ts +32 -0
  93. package/extensions/orchestrator/review-ui.ts +204 -0
  94. package/extensions/orchestrator/rule-placeholders.ts +12 -0
  95. package/extensions/orchestrator/rules.ts +481 -0
  96. package/extensions/orchestrator/session-search.ts +243 -0
  97. package/extensions/orchestrator/session-validation.ts +374 -0
  98. package/extensions/orchestrator/situation-report.ts +370 -0
  99. package/extensions/orchestrator/status-bar.ts +31 -0
  100. package/extensions/orchestrator/status-line.ts +192 -0
  101. package/extensions/orchestrator/status.ts +110 -0
  102. package/extensions/orchestrator/subagent-tool.ts +1748 -0
  103. package/extensions/orchestrator/task-lifecycle.ts +88 -0
  104. package/extensions/orchestrator/utils.ts +227 -0
  105. package/extensions/pidash/index.ts +15 -0
  106. package/extensions/pidash/pidash.ts +941 -0
  107. package/extensions/pidiff/index.ts +13 -0
  108. package/extensions/pidiff/pidiff.ts +369 -0
  109. package/extensions/providers/acpx-driver.ts +479 -0
  110. package/extensions/providers/built-in-drivers.ts +52 -0
  111. package/extensions/providers/claude-driver.ts +319 -0
  112. package/extensions/providers/cursor-acpx-driver.ts +398 -0
  113. package/extensions/providers/cursor-cli-driver.ts +484 -0
  114. package/extensions/providers/gemini-driver.ts +302 -0
  115. package/extensions/providers/index.ts +513 -0
  116. package/extensions/shared/build-system-prompt.ts +57 -0
  117. package/extensions/shared/create-runtime-provider.ts +190 -0
  118. package/extensions/shared/daemon-manager.ts +248 -0
  119. package/extensions/shared/file-logger.ts +115 -0
  120. package/extensions/shared/managed-refresh.ts +211 -0
  121. package/extensions/shared/provider-driver.ts +295 -0
  122. package/extensions/shared/provider-errors.ts +305 -0
  123. package/extensions/shared/provider-registry.ts +388 -0
  124. package/extensions/shared/stream-builder.ts +275 -0
  125. package/extensions/shared/types.ts +20 -0
  126. package/extensions/shared/ui/README.md +10 -0
  127. package/extensions/shared/ui/badge.tsx +52 -0
  128. package/extensions/shared/ui/button.tsx +58 -0
  129. package/extensions/shared/ui/collapsible.tsx +21 -0
  130. package/extensions/shared/ui/dropdown-menu.tsx +266 -0
  131. package/extensions/shared/ui/input.tsx +20 -0
  132. package/extensions/shared/ui/popover.tsx +114 -0
  133. package/extensions/shared/ui/resizable.tsx +48 -0
  134. package/extensions/shared/ui/scroll-area.tsx +53 -0
  135. package/extensions/shared/ui/select.tsx +201 -0
  136. package/extensions/shared/ui/separator.tsx +25 -0
  137. package/extensions/shared/ui/tooltip.tsx +64 -0
  138. package/extensions/shared/ws-client.ts +74 -0
  139. package/package.json +59 -0
  140. package/prompts/coderabbit-rate-limit.md +95 -0
  141. package/prompts/create-coms-feature-manager.md +186 -0
  142. package/prompts/create-skill.md +128 -0
  143. package/prompts/domain-model.md +109 -0
  144. package/prompts/external-ai.md +665 -0
  145. package/prompts/implement-and-review.md +25 -0
  146. package/prompts/implement.md +26 -0
  147. package/prompts/issue-review.md +256 -0
  148. package/prompts/pr-review.md +753 -0
  149. package/prompts/query-db.md +154 -0
  150. package/prompts/refine-review.md +208 -0
  151. package/prompts/release.md +235 -0
  152. package/prompts/remember.md +33 -0
  153. package/prompts/review-handler-status.md +27 -0
  154. package/prompts/review-handler.md +677 -0
  155. package/prompts/review-local.md +159 -0
  156. package/prompts/scout-and-plan.md +21 -0
  157. package/rules/00-orchestrator-core.md +42 -0
  158. package/rules/05-issue-first-workflow.md +119 -0
  159. package/rules/10-agent-routing.md +58 -0
  160. package/rules/15-mcp-launchpad.md +46 -0
  161. package/rules/20-code-review-loop.md +234 -0
  162. package/rules/25-documentation-updates.md +15 -0
  163. package/rules/30-prompt-templates.md +19 -0
  164. package/rules/35-memory.md +240 -0
  165. package/rules/40-critical-rules.md +124 -0
  166. package/rules/45-file-preview.md +29 -0
  167. package/rules/50-agent-bug-reporting.md +90 -0
  168. package/rules/55-coms-protocol.md +63 -0
  169. package/rules/60-task-tracking.md +66 -0
  170. package/skills/conflict-resolver/SKILL.md +213 -0
  171. package/skills/skill-creator/SKILL.md +85 -0
  172. package/skills/systematic-debugging/SKILL.md +353 -0
  173. package/skills/test-driven-development/SKILL.md +335 -0
  174. package/skills/update-agents-md/SKILL.md +282 -0
  175. package/templates/coms-feature-manager-prompt.md +313 -0
@@ -0,0 +1,266 @@
1
+ import * as React from "react"
2
+ import { Menu as MenuPrimitive } from "@base-ui/react/menu"
3
+
4
+ import { cn } from "@/lib/utils"
5
+ import { ChevronRightIcon, CheckIcon } from "lucide-react"
6
+
7
+ function DropdownMenu({ ...props }: MenuPrimitive.Root.Props) {
8
+ return <MenuPrimitive.Root data-slot="dropdown-menu" {...props} />
9
+ }
10
+
11
+ function DropdownMenuPortal({ ...props }: MenuPrimitive.Portal.Props) {
12
+ return <MenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />
13
+ }
14
+
15
+ function DropdownMenuTrigger({ ...props }: MenuPrimitive.Trigger.Props) {
16
+ return <MenuPrimitive.Trigger data-slot="dropdown-menu-trigger" {...props} />
17
+ }
18
+
19
+ function DropdownMenuContent({
20
+ align = "start",
21
+ alignOffset = 0,
22
+ side = "bottom",
23
+ sideOffset = 4,
24
+ className,
25
+ ...props
26
+ }: MenuPrimitive.Popup.Props &
27
+ Pick<
28
+ MenuPrimitive.Positioner.Props,
29
+ "align" | "alignOffset" | "side" | "sideOffset"
30
+ >) {
31
+ return (
32
+ <MenuPrimitive.Portal>
33
+ <MenuPrimitive.Positioner
34
+ className="isolate z-50 outline-none"
35
+ align={align}
36
+ alignOffset={alignOffset}
37
+ side={side}
38
+ sideOffset={sideOffset}
39
+ >
40
+ <MenuPrimitive.Popup
41
+ data-slot="dropdown-menu-content"
42
+ className={cn("z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 outline-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:overflow-hidden data-closed:fade-out-0 data-closed:zoom-out-95", className )}
43
+ {...props}
44
+ />
45
+ </MenuPrimitive.Positioner>
46
+ </MenuPrimitive.Portal>
47
+ )
48
+ }
49
+
50
+ function DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props) {
51
+ return <MenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
52
+ }
53
+
54
+ function DropdownMenuLabel({
55
+ className,
56
+ inset,
57
+ ...props
58
+ }: MenuPrimitive.GroupLabel.Props & {
59
+ inset?: boolean
60
+ }) {
61
+ return (
62
+ <MenuPrimitive.GroupLabel
63
+ data-slot="dropdown-menu-label"
64
+ data-inset={inset}
65
+ className={cn(
66
+ "px-1.5 py-1 text-xs font-medium text-muted-foreground data-inset:pl-7",
67
+ className
68
+ )}
69
+ {...props}
70
+ />
71
+ )
72
+ }
73
+
74
+ function DropdownMenuItem({
75
+ className,
76
+ inset,
77
+ variant = "default",
78
+ ...props
79
+ }: MenuPrimitive.Item.Props & {
80
+ inset?: boolean
81
+ variant?: "default" | "destructive"
82
+ }) {
83
+ return (
84
+ <MenuPrimitive.Item
85
+ data-slot="dropdown-menu-item"
86
+ data-inset={inset}
87
+ data-variant={variant}
88
+ className={cn(
89
+ "group/dropdown-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive",
90
+ className
91
+ )}
92
+ {...props}
93
+ />
94
+ )
95
+ }
96
+
97
+ function DropdownMenuSub({ ...props }: MenuPrimitive.SubmenuRoot.Props) {
98
+ return <MenuPrimitive.SubmenuRoot data-slot="dropdown-menu-sub" {...props} />
99
+ }
100
+
101
+ function DropdownMenuSubTrigger({
102
+ className,
103
+ inset,
104
+ children,
105
+ ...props
106
+ }: MenuPrimitive.SubmenuTrigger.Props & {
107
+ inset?: boolean
108
+ }) {
109
+ return (
110
+ <MenuPrimitive.SubmenuTrigger
111
+ data-slot="dropdown-menu-sub-trigger"
112
+ data-inset={inset}
113
+ className={cn(
114
+ "flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-popup-open:bg-accent data-popup-open:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
115
+ className
116
+ )}
117
+ {...props}
118
+ >
119
+ {children}
120
+ <ChevronRightIcon className="ml-auto" />
121
+ </MenuPrimitive.SubmenuTrigger>
122
+ )
123
+ }
124
+
125
+ function DropdownMenuSubContent({
126
+ align = "start",
127
+ alignOffset = -3,
128
+ side = "right",
129
+ sideOffset = 0,
130
+ className,
131
+ ...props
132
+ }: React.ComponentProps<typeof DropdownMenuContent>) {
133
+ return (
134
+ <DropdownMenuContent
135
+ data-slot="dropdown-menu-sub-content"
136
+ className={cn("w-auto min-w-[96px] rounded-lg bg-popover p-1 text-popover-foreground shadow-lg ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className )}
137
+ align={align}
138
+ alignOffset={alignOffset}
139
+ side={side}
140
+ sideOffset={sideOffset}
141
+ {...props}
142
+ />
143
+ )
144
+ }
145
+
146
+ function DropdownMenuCheckboxItem({
147
+ className,
148
+ children,
149
+ checked,
150
+ inset,
151
+ ...props
152
+ }: MenuPrimitive.CheckboxItem.Props & {
153
+ inset?: boolean
154
+ }) {
155
+ return (
156
+ <MenuPrimitive.CheckboxItem
157
+ data-slot="dropdown-menu-checkbox-item"
158
+ data-inset={inset}
159
+ className={cn(
160
+ "relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
161
+ className
162
+ )}
163
+ checked={checked}
164
+ {...props}
165
+ >
166
+ <span
167
+ className="pointer-events-none absolute right-2 flex items-center justify-center"
168
+ data-slot="dropdown-menu-checkbox-item-indicator"
169
+ >
170
+ <MenuPrimitive.CheckboxItemIndicator>
171
+ <CheckIcon
172
+ />
173
+ </MenuPrimitive.CheckboxItemIndicator>
174
+ </span>
175
+ {children}
176
+ </MenuPrimitive.CheckboxItem>
177
+ )
178
+ }
179
+
180
+ function DropdownMenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.Props) {
181
+ return (
182
+ <MenuPrimitive.RadioGroup
183
+ data-slot="dropdown-menu-radio-group"
184
+ {...props}
185
+ />
186
+ )
187
+ }
188
+
189
+ function DropdownMenuRadioItem({
190
+ className,
191
+ children,
192
+ inset,
193
+ ...props
194
+ }: MenuPrimitive.RadioItem.Props & {
195
+ inset?: boolean
196
+ }) {
197
+ return (
198
+ <MenuPrimitive.RadioItem
199
+ data-slot="dropdown-menu-radio-item"
200
+ data-inset={inset}
201
+ className={cn(
202
+ "relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
203
+ className
204
+ )}
205
+ {...props}
206
+ >
207
+ <span
208
+ className="pointer-events-none absolute right-2 flex items-center justify-center"
209
+ data-slot="dropdown-menu-radio-item-indicator"
210
+ >
211
+ <MenuPrimitive.RadioItemIndicator>
212
+ <CheckIcon
213
+ />
214
+ </MenuPrimitive.RadioItemIndicator>
215
+ </span>
216
+ {children}
217
+ </MenuPrimitive.RadioItem>
218
+ )
219
+ }
220
+
221
+ function DropdownMenuSeparator({
222
+ className,
223
+ ...props
224
+ }: MenuPrimitive.Separator.Props) {
225
+ return (
226
+ <MenuPrimitive.Separator
227
+ data-slot="dropdown-menu-separator"
228
+ className={cn("-mx-1 my-1 h-px bg-border", className)}
229
+ {...props}
230
+ />
231
+ )
232
+ }
233
+
234
+ function DropdownMenuShortcut({
235
+ className,
236
+ ...props
237
+ }: React.ComponentProps<"span">) {
238
+ return (
239
+ <span
240
+ data-slot="dropdown-menu-shortcut"
241
+ className={cn(
242
+ "ml-auto text-xs tracking-widest text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground",
243
+ className
244
+ )}
245
+ {...props}
246
+ />
247
+ )
248
+ }
249
+
250
+ export {
251
+ DropdownMenu,
252
+ DropdownMenuPortal,
253
+ DropdownMenuTrigger,
254
+ DropdownMenuContent,
255
+ DropdownMenuGroup,
256
+ DropdownMenuLabel,
257
+ DropdownMenuItem,
258
+ DropdownMenuCheckboxItem,
259
+ DropdownMenuRadioGroup,
260
+ DropdownMenuRadioItem,
261
+ DropdownMenuSeparator,
262
+ DropdownMenuShortcut,
263
+ DropdownMenuSub,
264
+ DropdownMenuSubTrigger,
265
+ DropdownMenuSubContent,
266
+ }
@@ -0,0 +1,20 @@
1
+ import * as React from "react"
2
+ import { Input as InputPrimitive } from "@base-ui/react/input"
3
+
4
+ import { cn } from "@/lib/utils"
5
+
6
+ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
7
+ return (
8
+ <InputPrimitive
9
+ type={type}
10
+ data-slot="input"
11
+ className={cn(
12
+ "h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
13
+ className
14
+ )}
15
+ {...props}
16
+ />
17
+ )
18
+ }
19
+
20
+ export { Input }
@@ -0,0 +1,114 @@
1
+ import * as React from "react";
2
+ import * as ReactDOM from "react-dom";
3
+ import { cn } from "@/lib/utils";
4
+
5
+ interface PopoverProps {
6
+ children: React.ReactNode;
7
+ open?: boolean;
8
+ onOpenChange?: (open: boolean) => void;
9
+ }
10
+
11
+ const PopoverContext = React.createContext<{
12
+ open: boolean;
13
+ setOpen: (v: boolean) => void;
14
+ triggerRef: React.RefObject<HTMLButtonElement | null>;
15
+ }>({ open: false, setOpen: () => {}, triggerRef: { current: null } });
16
+
17
+ export function Popover({ children, open: controlledOpen, onOpenChange }: PopoverProps) {
18
+ const [internalOpen, setInternalOpen] = React.useState(false);
19
+ const triggerRef = React.useRef<HTMLButtonElement | null>(null);
20
+ const open = controlledOpen ?? internalOpen;
21
+ const setOpen = onOpenChange ?? setInternalOpen;
22
+ return <PopoverContext.Provider value={{ open, setOpen, triggerRef }}>{children}</PopoverContext.Provider>;
23
+ }
24
+
25
+ export function PopoverTrigger({ children, className }: { children: React.ReactNode; className?: string; asChild?: boolean }) {
26
+ const { open, setOpen, triggerRef } = React.useContext(PopoverContext);
27
+ return (
28
+ <button ref={triggerRef} className={className} onClick={(e) => { e.stopPropagation(); setOpen(!open); }} type="button">
29
+ {children}
30
+ </button>
31
+ );
32
+ }
33
+
34
+ export function PopoverContent({ children, className, side = "top" }: { children: React.ReactNode; className?: string; align?: string; side?: "top" | "bottom" }) {
35
+ const { open, setOpen, triggerRef } = React.useContext(PopoverContext);
36
+ const ref = React.useRef<HTMLDivElement>(null);
37
+ const [pos, setPos] = React.useState<{ top: number; left: number } | null>(null);
38
+
39
+ const updatePosition = React.useCallback(() => {
40
+ const trigger = triggerRef.current;
41
+ const popover = ref.current;
42
+ if (!trigger || !popover) return;
43
+
44
+ const rect = trigger.getBoundingClientRect();
45
+ const popRect = popover.getBoundingClientRect();
46
+
47
+ // Align right edge of popover with right edge of trigger
48
+ let left = rect.right - popRect.width;
49
+ // Clamp so it doesn't overflow left or right edge of viewport
50
+ left = Math.max(4, Math.min(left, window.innerWidth - popRect.width - 4));
51
+
52
+ let top: number;
53
+ if (side === "top") {
54
+ top = rect.top - popRect.height - 8;
55
+ // If it would go above viewport, flip to bottom
56
+ if (top < 4) top = rect.bottom + 8;
57
+ } else {
58
+ top = rect.bottom + 8;
59
+ // If it would go below viewport, flip to top
60
+ if (top + popRect.height > window.innerHeight - 4) top = rect.top - popRect.height - 8;
61
+ }
62
+
63
+ setPos({ top, left });
64
+ }, [triggerRef, side]);
65
+
66
+ // Position calculation: run after mount and on scroll/resize
67
+ React.useEffect(() => {
68
+ if (!open) return;
69
+ // Initial position after the portal element mounts
70
+ requestAnimationFrame(updatePosition);
71
+
72
+ window.addEventListener("scroll", updatePosition, true);
73
+ window.addEventListener("resize", updatePosition);
74
+ return () => {
75
+ window.removeEventListener("scroll", updatePosition, true);
76
+ window.removeEventListener("resize", updatePosition);
77
+ };
78
+ }, [open, updatePosition]);
79
+
80
+ // Click-outside-to-close
81
+ React.useEffect(() => {
82
+ if (!open) return;
83
+
84
+ const handler = (e: MouseEvent) => {
85
+ const target = e.target as Node;
86
+ if (ref.current?.contains(target)) return;
87
+ if (triggerRef.current?.contains(target)) return;
88
+ setOpen(false);
89
+ };
90
+
91
+ const timer = setTimeout(() => {
92
+ document.addEventListener("mousedown", handler);
93
+ }, 10);
94
+
95
+ return () => {
96
+ clearTimeout(timer);
97
+ document.removeEventListener("mousedown", handler);
98
+ };
99
+ }, [open, setOpen, triggerRef]);
100
+
101
+ if (!open) return null;
102
+
103
+ const content = (
104
+ <div
105
+ ref={ref}
106
+ style={pos ? { position: "fixed", top: pos.top, left: pos.left } : { position: "fixed", top: -9999, left: -9999 }}
107
+ className={cn("z-[9999] rounded-md border border-border bg-popover p-2 shadow-lg", className)}
108
+ >
109
+ {children}
110
+ </div>
111
+ );
112
+
113
+ return ReactDOM.createPortal(content, document.body);
114
+ }
@@ -0,0 +1,48 @@
1
+ import * as ResizablePrimitive from "react-resizable-panels"
2
+
3
+ import { cn } from "@/lib/utils"
4
+
5
+ function ResizablePanelGroup({
6
+ className,
7
+ ...props
8
+ }: ResizablePrimitive.GroupProps) {
9
+ return (
10
+ <ResizablePrimitive.Group
11
+ data-slot="resizable-panel-group"
12
+ className={cn(
13
+ "flex h-full w-full aria-[orientation=vertical]:flex-col",
14
+ className
15
+ )}
16
+ {...props}
17
+ />
18
+ )
19
+ }
20
+
21
+ function ResizablePanel({ ...props }: ResizablePrimitive.PanelProps) {
22
+ return <ResizablePrimitive.Panel data-slot="resizable-panel" {...props} />
23
+ }
24
+
25
+ function ResizableHandle({
26
+ withHandle,
27
+ className,
28
+ ...props
29
+ }: ResizablePrimitive.SeparatorProps & {
30
+ withHandle?: boolean
31
+ }) {
32
+ return (
33
+ <ResizablePrimitive.Separator
34
+ data-slot="resizable-handle"
35
+ className={cn(
36
+ "relative flex w-px items-center justify-center bg-border ring-offset-background after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-hidden aria-[orientation=horizontal]:h-px aria-[orientation=horizontal]:w-full aria-[orientation=horizontal]:after:left-0 aria-[orientation=horizontal]:after:h-1 aria-[orientation=horizontal]:after:w-full aria-[orientation=horizontal]:after:translate-x-0 aria-[orientation=horizontal]:after:-translate-y-1/2 [&[aria-orientation=horizontal]>div]:rotate-90",
37
+ className
38
+ )}
39
+ {...props}
40
+ >
41
+ {withHandle && (
42
+ <div className="z-10 flex h-6 w-1 shrink-0 rounded-lg bg-border" />
43
+ )}
44
+ </ResizablePrimitive.Separator>
45
+ )
46
+ }
47
+
48
+ export { ResizableHandle, ResizablePanel, ResizablePanelGroup }
@@ -0,0 +1,53 @@
1
+ import * as React from "react"
2
+ import { ScrollArea as ScrollAreaPrimitive } from "@base-ui/react/scroll-area"
3
+
4
+ import { cn } from "@/lib/utils"
5
+
6
+ function ScrollArea({
7
+ className,
8
+ children,
9
+ ...props
10
+ }: ScrollAreaPrimitive.Root.Props) {
11
+ return (
12
+ <ScrollAreaPrimitive.Root
13
+ data-slot="scroll-area"
14
+ className={cn("relative", className)}
15
+ {...props}
16
+ >
17
+ <ScrollAreaPrimitive.Viewport
18
+ data-slot="scroll-area-viewport"
19
+ className="size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1"
20
+ >
21
+ {children}
22
+ </ScrollAreaPrimitive.Viewport>
23
+ <ScrollBar />
24
+ <ScrollAreaPrimitive.Corner />
25
+ </ScrollAreaPrimitive.Root>
26
+ )
27
+ }
28
+
29
+ function ScrollBar({
30
+ className,
31
+ orientation = "vertical",
32
+ ...props
33
+ }: ScrollAreaPrimitive.Scrollbar.Props) {
34
+ return (
35
+ <ScrollAreaPrimitive.Scrollbar
36
+ data-slot="scroll-area-scrollbar"
37
+ data-orientation={orientation}
38
+ orientation={orientation}
39
+ className={cn(
40
+ "flex touch-none p-px transition-colors select-none data-horizontal:h-2.5 data-horizontal:flex-col data-horizontal:border-t data-horizontal:border-t-transparent data-vertical:h-full data-vertical:w-2.5 data-vertical:border-l data-vertical:border-l-transparent",
41
+ className
42
+ )}
43
+ {...props}
44
+ >
45
+ <ScrollAreaPrimitive.Thumb
46
+ data-slot="scroll-area-thumb"
47
+ className="relative flex-1 rounded-full bg-border"
48
+ />
49
+ </ScrollAreaPrimitive.Scrollbar>
50
+ )
51
+ }
52
+
53
+ export { ScrollArea, ScrollBar }