@sero-ai/ui 0.3.1 → 0.4.0
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/.turbo/turbo-build.log +628 -0
- package/.turbo/turbo-typecheck.log +1 -1
- package/CHANGELOG.md +38 -0
- package/dist/components/context-editor/CapabilitySection.cjs +57 -0
- package/dist/components/context-editor/CapabilitySection.d.cts +20 -0
- package/dist/components/context-editor/CapabilitySection.d.ts +20 -0
- package/dist/components/context-editor/CapabilitySection.js +57 -0
- package/dist/components/context-editor/ContextEditor.cjs +108 -0
- package/dist/components/context-editor/ContextEditor.d.cts +26 -0
- package/dist/components/context-editor/ContextEditor.d.ts +26 -0
- package/dist/components/context-editor/ContextEditor.js +108 -0
- package/dist/components/context-editor/PresetBar.cjs +71 -0
- package/dist/components/context-editor/PresetBar.d.cts +19 -0
- package/dist/components/context-editor/PresetBar.d.ts +19 -0
- package/dist/components/context-editor/PresetBar.js +71 -0
- package/dist/components/context-editor/SkillsSection.cjs +31 -0
- package/dist/components/context-editor/SkillsSection.d.cts +14 -0
- package/dist/components/context-editor/SkillsSection.d.ts +14 -0
- package/dist/components/context-editor/SkillsSection.js +31 -0
- package/dist/components/context-editor/SystemPromptSection.cjs +58 -0
- package/dist/components/context-editor/SystemPromptSection.d.cts +25 -0
- package/dist/components/context-editor/SystemPromptSection.d.ts +25 -0
- package/dist/components/context-editor/SystemPromptSection.js +58 -0
- package/dist/components/context-editor/ToolsSection.cjs +31 -0
- package/dist/components/context-editor/ToolsSection.d.cts +14 -0
- package/dist/components/context-editor/ToolsSection.d.ts +14 -0
- package/dist/components/context-editor/ToolsSection.js +31 -0
- package/dist/components/context-editor/index.cjs +8 -0
- package/dist/components/context-editor/index.d.cts +5 -0
- package/dist/components/context-editor/index.d.ts +5 -0
- package/dist/components/context-editor/index.js +8 -0
- package/dist/components/context-editor/parts.cjs +184 -0
- package/dist/components/context-editor/parts.d.cts +32 -0
- package/dist/components/context-editor/parts.d.ts +32 -0
- package/dist/components/context-editor/parts.js +184 -0
- package/dist/components/context-editor/use-context-editor-model.cjs +194 -0
- package/dist/components/context-editor/use-context-editor-model.d.cts +57 -0
- package/dist/components/context-editor/use-context-editor-model.d.ts +57 -0
- package/dist/components/context-editor/use-context-editor-model.js +194 -0
- package/dist/components/dashboard/activity-list.cjs +59 -0
- package/dist/components/dashboard/activity-list.d.cts +27 -0
- package/dist/components/dashboard/activity-list.d.ts +27 -0
- package/dist/components/dashboard/activity-list.js +59 -0
- package/dist/components/dashboard/catalog.cjs +322 -0
- package/dist/components/dashboard/catalog.d.cts +14 -0
- package/dist/components/dashboard/catalog.d.ts +14 -0
- package/dist/components/dashboard/catalog.js +322 -0
- package/dist/components/dashboard/data-boundary.cjs +29 -0
- package/dist/components/dashboard/data-boundary.d.cts +21 -0
- package/dist/components/dashboard/data-boundary.d.ts +21 -0
- package/dist/components/dashboard/data-boundary.js +29 -0
- package/dist/components/dashboard/empty-state.cjs +49 -0
- package/dist/components/dashboard/empty-state.d.cts +20 -0
- package/dist/components/dashboard/empty-state.d.ts +20 -0
- package/dist/components/dashboard/empty-state.js +49 -0
- package/dist/components/dashboard/icon-button.cjs +40 -0
- package/dist/components/dashboard/icon-button.d.cts +24 -0
- package/dist/components/dashboard/icon-button.d.ts +24 -0
- package/dist/components/dashboard/icon-button.js +40 -0
- package/dist/components/dashboard/index.cjs +15 -0
- package/dist/components/dashboard/index.d.cts +24 -0
- package/dist/components/dashboard/index.d.ts +24 -0
- package/dist/components/dashboard/index.js +15 -0
- package/dist/components/dashboard/item-list.cjs +71 -0
- package/dist/components/dashboard/item-list.d.cts +28 -0
- package/dist/components/dashboard/item-list.d.ts +28 -0
- package/dist/components/dashboard/item-list.js +71 -0
- package/dist/components/dashboard/key-value.cjs +39 -0
- package/dist/components/dashboard/key-value.d.cts +17 -0
- package/dist/components/dashboard/key-value.d.ts +17 -0
- package/dist/components/dashboard/key-value.js +39 -0
- package/dist/components/dashboard/layout.cjs +193 -0
- package/dist/components/dashboard/layout.d.cts +91 -0
- package/dist/components/dashboard/layout.d.ts +91 -0
- package/dist/components/dashboard/layout.js +193 -0
- package/dist/components/dashboard/metric.cjs +98 -0
- package/dist/components/dashboard/metric.d.cts +44 -0
- package/dist/components/dashboard/metric.d.ts +44 -0
- package/dist/components/dashboard/metric.js +98 -0
- package/dist/components/dashboard/progress-ring.cjs +77 -0
- package/dist/components/dashboard/progress-ring.d.cts +25 -0
- package/dist/components/dashboard/progress-ring.d.ts +25 -0
- package/dist/components/dashboard/progress-ring.js +77 -0
- package/dist/components/dashboard/skeletons.cjs +54 -0
- package/dist/components/dashboard/skeletons.d.cts +15 -0
- package/dist/components/dashboard/skeletons.d.ts +15 -0
- package/dist/components/dashboard/skeletons.js +54 -0
- package/dist/components/dashboard/spacing.cjs +10 -0
- package/dist/components/dashboard/spacing.d.cts +4 -0
- package/dist/components/dashboard/spacing.d.ts +4 -0
- package/dist/components/dashboard/spacing.js +10 -0
- package/dist/components/dashboard/stale-indicator.cjs +42 -0
- package/dist/components/dashboard/stale-indicator.d.cts +15 -0
- package/dist/components/dashboard/stale-indicator.d.ts +15 -0
- package/dist/components/dashboard/stale-indicator.js +42 -0
- package/dist/components/dashboard/status.cjs +62 -0
- package/dist/components/dashboard/status.d.cts +15 -0
- package/dist/components/dashboard/status.d.ts +15 -0
- package/dist/components/dashboard/status.js +62 -0
- package/dist/components/dashboard/tone.cjs +26 -0
- package/dist/components/dashboard/tone.d.cts +9 -0
- package/dist/components/dashboard/tone.d.ts +9 -0
- package/dist/components/dashboard/tone.js +26 -0
- package/dist/components/dashboard/typography.cjs +99 -0
- package/dist/components/dashboard/typography.d.cts +57 -0
- package/dist/components/dashboard/typography.d.ts +57 -0
- package/dist/components/dashboard/typography.js +99 -0
- package/dist/components/reference/ActivityExample.cjs +47 -0
- package/dist/components/reference/ActivityExample.d.cts +5 -0
- package/dist/components/reference/ActivityExample.d.ts +5 -0
- package/dist/components/reference/ActivityExample.js +47 -0
- package/dist/components/reference/ResourceExample.cjs +54 -0
- package/dist/components/reference/ResourceExample.d.cts +5 -0
- package/dist/components/reference/ResourceExample.d.ts +5 -0
- package/dist/components/reference/ResourceExample.js +54 -0
- package/dist/components/reference/SchedulerExample.cjs +68 -0
- package/dist/components/reference/SchedulerExample.d.cts +5 -0
- package/dist/components/reference/SchedulerExample.d.ts +5 -0
- package/dist/components/reference/SchedulerExample.js +68 -0
- package/dist/components/reference/StarterExample.cjs +34 -0
- package/dist/components/reference/StarterExample.d.cts +5 -0
- package/dist/components/reference/StarterExample.d.ts +5 -0
- package/dist/components/reference/StarterExample.js +34 -0
- package/dist/components/reference/index.cjs +10 -0
- package/dist/components/reference/index.d.cts +5 -0
- package/dist/components/reference/index.d.ts +5 -0
- package/dist/components/reference/index.js +10 -0
- package/dist/components/ui/badge.cjs +5 -1
- package/dist/components/ui/badge.d.cts +1 -1
- package/dist/components/ui/badge.d.ts +1 -1
- package/dist/components/ui/badge.js +5 -1
- package/dist/dashboard-catalog.cjs +8 -0
- package/dist/dashboard-catalog.d.cts +1 -0
- package/dist/dashboard-catalog.d.ts +1 -0
- package/dist/dashboard-catalog.js +8 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +1 -0
- package/dist/reference.cjs +12 -0
- package/dist/reference.d.cts +5 -0
- package/dist/reference.d.ts +5 -0
- package/dist/reference.js +12 -0
- package/dist/styles/glass-board.css +43 -0
- package/dist/styles/globals.css +497 -0
- package/dist/styles/plugin.css +4 -0
- package/package.json +71 -30
- package/src/components/context-editor/CapabilitySection.tsx +85 -0
- package/src/components/context-editor/ContextEditor.tsx +138 -0
- package/src/components/context-editor/PresetBar.tsx +94 -0
- package/src/components/context-editor/SkillsSection.tsx +37 -0
- package/src/components/context-editor/SystemPromptSection.tsx +88 -0
- package/src/components/context-editor/ToolsSection.tsx +37 -0
- package/src/components/context-editor/index.ts +7 -0
- package/src/components/context-editor/parts.tsx +217 -0
- package/src/components/context-editor/use-context-editor-model.ts +296 -0
- package/src/components/dashboard/__tests__/catalog.test.ts +57 -0
- package/src/components/dashboard/__tests__/glass.test.tsx +42 -0
- package/src/components/dashboard/__tests__/state.test.tsx +110 -0
- package/src/components/dashboard/__tests__/variants.test.tsx +95 -0
- package/src/components/dashboard/activity-list.tsx +99 -0
- package/src/components/dashboard/catalog.ts +351 -0
- package/src/components/dashboard/data-boundary.tsx +54 -0
- package/src/components/dashboard/empty-state.tsx +70 -0
- package/src/components/dashboard/icon-button.tsx +58 -0
- package/src/components/dashboard/index.ts +21 -0
- package/src/components/dashboard/item-list.tsx +106 -0
- package/src/components/dashboard/key-value.tsx +54 -0
- package/src/components/dashboard/layout.tsx +286 -0
- package/src/components/dashboard/metric.tsx +139 -0
- package/src/components/dashboard/progress-ring.tsx +100 -0
- package/src/components/dashboard/skeletons.tsx +73 -0
- package/src/components/dashboard/spacing.ts +14 -0
- package/src/components/dashboard/stale-indicator.tsx +55 -0
- package/src/components/dashboard/status.tsx +75 -0
- package/src/components/dashboard/tone.ts +35 -0
- package/src/components/dashboard/typography.tsx +151 -0
- package/src/components/reference/ActivityExample.tsx +68 -0
- package/src/components/reference/ResourceExample.tsx +78 -0
- package/src/components/reference/SchedulerExample.tsx +88 -0
- package/src/components/reference/StarterExample.tsx +48 -0
- package/src/components/reference/index.ts +10 -0
- package/src/components/ui/badge.tsx +6 -0
- package/src/dashboard-catalog.ts +13 -0
- package/src/index.ts +5 -0
- package/src/reference.ts +15 -0
- package/src/styles/glass-board.css +43 -0
- package/src/styles/globals.css +59 -0
- package/tsup.config.ts +11 -3
- package/vitest.config.ts +8 -0
- package/LICENSE +0 -201
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { LucideIcon } from 'lucide-react';
|
|
2
|
+
import type { ContextSkillInfo, ContextToolInfo } from '@sero-ai/common';
|
|
3
|
+
import { Switch } from '../ui/switch';
|
|
4
|
+
import { ContextSection, ToggleRow } from './parts';
|
|
5
|
+
|
|
6
|
+
interface CapabilitySectionProps<TItem extends ContextToolInfo | ContextSkillInfo> {
|
|
7
|
+
icon: LucideIcon;
|
|
8
|
+
title: string;
|
|
9
|
+
tint: 'amber' | 'violet';
|
|
10
|
+
includeAllLabel: string;
|
|
11
|
+
emptyLabel: string;
|
|
12
|
+
items: TItem[];
|
|
13
|
+
allDisabled: boolean;
|
|
14
|
+
enabledCount: number;
|
|
15
|
+
isEnabled: (name: string) => boolean;
|
|
16
|
+
onToggle: (name: string) => void;
|
|
17
|
+
onToggleAll: (disabled: boolean) => void;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function CapabilitySection<TItem extends ContextToolInfo | ContextSkillInfo>({
|
|
21
|
+
icon,
|
|
22
|
+
title,
|
|
23
|
+
tint,
|
|
24
|
+
includeAllLabel,
|
|
25
|
+
emptyLabel,
|
|
26
|
+
items,
|
|
27
|
+
allDisabled,
|
|
28
|
+
enabledCount,
|
|
29
|
+
isEnabled,
|
|
30
|
+
onToggle,
|
|
31
|
+
onToggleAll,
|
|
32
|
+
}: CapabilitySectionProps<TItem>) {
|
|
33
|
+
const badgeVariant = allDisabled
|
|
34
|
+
? 'disabled' as const
|
|
35
|
+
: enabledCount < items.length
|
|
36
|
+
? 'partial' as const
|
|
37
|
+
: 'default' as const;
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<ContextSection
|
|
41
|
+
icon={icon}
|
|
42
|
+
title={title}
|
|
43
|
+
tint={tint}
|
|
44
|
+
count={items.length}
|
|
45
|
+
badge={
|
|
46
|
+
items.length > 0 && enabledCount < items.length
|
|
47
|
+
? `${enabledCount}/${items.length} included`
|
|
48
|
+
: undefined
|
|
49
|
+
}
|
|
50
|
+
badgeVariant={badgeVariant}
|
|
51
|
+
defaultOpen={false}
|
|
52
|
+
>
|
|
53
|
+
<div className="space-y-1">
|
|
54
|
+
{items.length > 0 && (
|
|
55
|
+
<div className="mb-1 flex items-center justify-between rounded-md border-b border-border/20 px-2 pb-2">
|
|
56
|
+
<span className="text-[11px] font-medium text-[var(--text-secondary)]">
|
|
57
|
+
{includeAllLabel}
|
|
58
|
+
</span>
|
|
59
|
+
<Switch
|
|
60
|
+
size="sm"
|
|
61
|
+
checked={!allDisabled}
|
|
62
|
+
onCheckedChange={(checked) => onToggleAll(!checked)}
|
|
63
|
+
/>
|
|
64
|
+
</div>
|
|
65
|
+
)}
|
|
66
|
+
|
|
67
|
+
{items.map((item) => (
|
|
68
|
+
<ToggleRow
|
|
69
|
+
key={item.name}
|
|
70
|
+
name={item.name}
|
|
71
|
+
description={item.description}
|
|
72
|
+
enabled={isEnabled(item.name)}
|
|
73
|
+
onToggle={() => onToggle(item.name)}
|
|
74
|
+
/>
|
|
75
|
+
))}
|
|
76
|
+
|
|
77
|
+
{items.length === 0 && (
|
|
78
|
+
<span className="text-[11px] italic text-[var(--text-muted)]">
|
|
79
|
+
{emptyLabel}
|
|
80
|
+
</span>
|
|
81
|
+
)}
|
|
82
|
+
</div>
|
|
83
|
+
</ContextSection>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ContextEditor — shared, controlled context editor dialog.
|
|
3
|
+
*
|
|
4
|
+
* Edits a system prompt plus tool/skill enablement and saved presets, against
|
|
5
|
+
* an `available` context. Host-agnostic: the consumer supplies the available
|
|
6
|
+
* context, the current overrides, the preset list, and the persistence
|
|
7
|
+
* callbacks. Used by the desktop chat session editor and by app modules (e.g.
|
|
8
|
+
* the Orchestrator loop context override).
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { useState } from 'react';
|
|
12
|
+
import { AlertCircle, Loader2, Settings2 } from 'lucide-react';
|
|
13
|
+
import type { AvailableContext, ContextOverrides, ContextPreset } from '@sero-ai/common';
|
|
14
|
+
import {
|
|
15
|
+
Dialog,
|
|
16
|
+
DialogContent,
|
|
17
|
+
DialogDescription,
|
|
18
|
+
DialogFooter,
|
|
19
|
+
DialogHeader,
|
|
20
|
+
DialogTitle,
|
|
21
|
+
} from '../ui/dialog';
|
|
22
|
+
import { ScrollArea } from '../ui/scroll-area';
|
|
23
|
+
import { PresetBar } from './PresetBar';
|
|
24
|
+
import { SkillsSection } from './SkillsSection';
|
|
25
|
+
import { SystemPromptSection, type SystemPromptCopy } from './SystemPromptSection';
|
|
26
|
+
import { ToolsSection } from './ToolsSection';
|
|
27
|
+
import { useContextEditorModel, type ContextPresetBody } from './use-context-editor-model';
|
|
28
|
+
|
|
29
|
+
export interface ContextEditorProps {
|
|
30
|
+
open: boolean;
|
|
31
|
+
onOpenChange: (open: boolean) => void;
|
|
32
|
+
available: AvailableContext | null;
|
|
33
|
+
initialOverrides: ContextOverrides | null;
|
|
34
|
+
presets: ContextPreset[];
|
|
35
|
+
/** Persist the chosen overrides. Return false to keep the dialog open (error). */
|
|
36
|
+
onApply: (overrides: ContextOverrides | null) => Promise<boolean> | boolean;
|
|
37
|
+
onSavePreset: (name: string, preset: ContextPresetBody) => void;
|
|
38
|
+
onDeletePreset: (id: string) => void;
|
|
39
|
+
applyError?: string | null;
|
|
40
|
+
title?: string;
|
|
41
|
+
description?: string;
|
|
42
|
+
systemPromptCopy?: SystemPromptCopy;
|
|
43
|
+
applyLabel?: string;
|
|
44
|
+
/** Hide the Tools section (e.g. the Orchestrator picks tools per step, not per loop). */
|
|
45
|
+
hideTools?: boolean;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function ContextEditor({
|
|
49
|
+
open,
|
|
50
|
+
onOpenChange,
|
|
51
|
+
available,
|
|
52
|
+
initialOverrides,
|
|
53
|
+
presets,
|
|
54
|
+
onApply,
|
|
55
|
+
onSavePreset,
|
|
56
|
+
onDeletePreset,
|
|
57
|
+
applyError,
|
|
58
|
+
title = 'Context Editor',
|
|
59
|
+
description = 'Configure what is included in the LLM context.',
|
|
60
|
+
systemPromptCopy,
|
|
61
|
+
applyLabel = 'Apply',
|
|
62
|
+
hideTools = false,
|
|
63
|
+
}: ContextEditorProps) {
|
|
64
|
+
const model = useContextEditorModel({ open, available, initialOverrides, presets, onSavePreset, onDeletePreset });
|
|
65
|
+
const [applying, setApplying] = useState(false);
|
|
66
|
+
|
|
67
|
+
const handleApply = async () => {
|
|
68
|
+
setApplying(true);
|
|
69
|
+
try {
|
|
70
|
+
const ok = await onApply(model.buildOverrides());
|
|
71
|
+
if (ok !== false) onOpenChange(false);
|
|
72
|
+
} finally {
|
|
73
|
+
setApplying(false);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
79
|
+
<DialogContent
|
|
80
|
+
className="max-h-[85vh] overflow-hidden bg-[var(--bg-surface)] sm:max-w-[58rem]"
|
|
81
|
+
showCloseButton
|
|
82
|
+
>
|
|
83
|
+
<DialogHeader>
|
|
84
|
+
<DialogTitle className="flex items-center gap-2 text-sm">
|
|
85
|
+
<Settings2 className="size-4 text-[var(--text-muted)]" />
|
|
86
|
+
{title}
|
|
87
|
+
</DialogTitle>
|
|
88
|
+
<DialogDescription className="text-xs">{description}</DialogDescription>
|
|
89
|
+
</DialogHeader>
|
|
90
|
+
|
|
91
|
+
<PresetBar {...model.preset} />
|
|
92
|
+
|
|
93
|
+
{!available ? (
|
|
94
|
+
<div className="flex items-center justify-center gap-2 py-8">
|
|
95
|
+
<Loader2 className="size-4 animate-spin text-[var(--text-muted)]" />
|
|
96
|
+
<span className="text-xs text-[var(--text-muted)]">Loading context…</span>
|
|
97
|
+
</div>
|
|
98
|
+
) : (
|
|
99
|
+
<ScrollArea className="max-h-[65vh] overflow-hidden">
|
|
100
|
+
<div className="min-w-0 space-y-2 pr-2">
|
|
101
|
+
<SystemPromptSection
|
|
102
|
+
displayedPrompt={model.displayedPrompt}
|
|
103
|
+
systemPrompt={model.systemPrompt}
|
|
104
|
+
onSystemPromptChange={model.setSystemPrompt}
|
|
105
|
+
copy={systemPromptCopy}
|
|
106
|
+
/>
|
|
107
|
+
{!hideTools && <ToolsSection {...model.tools} />}
|
|
108
|
+
<SkillsSection {...model.skills} />
|
|
109
|
+
</div>
|
|
110
|
+
</ScrollArea>
|
|
111
|
+
)}
|
|
112
|
+
|
|
113
|
+
{applyError && (
|
|
114
|
+
<div className="flex items-start gap-2 rounded-md border border-status-error-border bg-status-error-muted px-3 py-2">
|
|
115
|
+
<AlertCircle className="mt-0.5 size-3.5 shrink-0 text-status-error" />
|
|
116
|
+
<span className="text-[11px] text-status-error">{applyError}</span>
|
|
117
|
+
</div>
|
|
118
|
+
)}
|
|
119
|
+
|
|
120
|
+
<DialogFooter>
|
|
121
|
+
<button type="button"
|
|
122
|
+
onClick={() => onOpenChange(false)}
|
|
123
|
+
className="rounded-md border border-border/50 px-3 py-1.5 text-xs text-[var(--text-secondary)] transition-colors hover:bg-[var(--bg-elevated)]"
|
|
124
|
+
>
|
|
125
|
+
Cancel
|
|
126
|
+
</button>
|
|
127
|
+
<button type="button"
|
|
128
|
+
onClick={() => { void handleApply(); }}
|
|
129
|
+
disabled={!available || applying}
|
|
130
|
+
className="rounded-md bg-[var(--accent-primary)] px-3 py-1.5 text-xs font-medium text-white transition-colors hover:bg-[var(--accent-hover)] disabled:opacity-50"
|
|
131
|
+
>
|
|
132
|
+
{applyLabel}
|
|
133
|
+
</button>
|
|
134
|
+
</DialogFooter>
|
|
135
|
+
</DialogContent>
|
|
136
|
+
</Dialog>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { RotateCcw, Save, Trash2 } from 'lucide-react';
|
|
2
|
+
import type { ContextPreset } from '@sero-ai/common';
|
|
3
|
+
import {
|
|
4
|
+
Select,
|
|
5
|
+
SelectContent,
|
|
6
|
+
SelectItem,
|
|
7
|
+
SelectTrigger,
|
|
8
|
+
SelectValue,
|
|
9
|
+
} from '../ui/select';
|
|
10
|
+
import { SavePresetInput } from './parts';
|
|
11
|
+
|
|
12
|
+
interface PresetBarProps {
|
|
13
|
+
allPresets: ContextPreset[];
|
|
14
|
+
activePresetId: string | null;
|
|
15
|
+
activeUserPreset: ContextPreset | null;
|
|
16
|
+
hasOverrides: boolean;
|
|
17
|
+
showSaveInput: boolean;
|
|
18
|
+
onPresetChange: (id: string) => void;
|
|
19
|
+
onDelete: (id: string) => void;
|
|
20
|
+
onReset: () => void;
|
|
21
|
+
onShowSave: () => void;
|
|
22
|
+
onSave: (name: string) => void;
|
|
23
|
+
onCancelSave: () => void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function PresetBar({
|
|
27
|
+
allPresets,
|
|
28
|
+
activePresetId,
|
|
29
|
+
activeUserPreset,
|
|
30
|
+
hasOverrides,
|
|
31
|
+
showSaveInput,
|
|
32
|
+
onPresetChange,
|
|
33
|
+
onDelete,
|
|
34
|
+
onReset,
|
|
35
|
+
onShowSave,
|
|
36
|
+
onSave,
|
|
37
|
+
onCancelSave,
|
|
38
|
+
}: PresetBarProps) {
|
|
39
|
+
return (
|
|
40
|
+
<>
|
|
41
|
+
<div className="flex items-center gap-2">
|
|
42
|
+
<span className="text-[11px] font-medium text-[var(--text-muted)]">
|
|
43
|
+
Preset:
|
|
44
|
+
</span>
|
|
45
|
+
<Select value={activePresetId ?? ''} onValueChange={onPresetChange}>
|
|
46
|
+
<SelectTrigger size="sm" className="h-7 w-40 text-xs">
|
|
47
|
+
<SelectValue placeholder="Custom" />
|
|
48
|
+
</SelectTrigger>
|
|
49
|
+
<SelectContent>
|
|
50
|
+
{allPresets.map((preset) => (
|
|
51
|
+
<SelectItem key={preset.id} value={preset.id}>
|
|
52
|
+
{preset.name}
|
|
53
|
+
</SelectItem>
|
|
54
|
+
))}
|
|
55
|
+
</SelectContent>
|
|
56
|
+
</Select>
|
|
57
|
+
|
|
58
|
+
{activeUserPreset && (
|
|
59
|
+
<button type="button"
|
|
60
|
+
onClick={() => onDelete(activeUserPreset.id)}
|
|
61
|
+
className="flex items-center gap-1 rounded-md px-1.5 py-1 text-[var(--text-muted)] transition-colors hover:bg-status-error-muted hover:text-status-error"
|
|
62
|
+
title={`Delete "${activeUserPreset.name}"`}
|
|
63
|
+
>
|
|
64
|
+
<Trash2 className="size-3" />
|
|
65
|
+
</button>
|
|
66
|
+
)}
|
|
67
|
+
|
|
68
|
+
{!showSaveInput && (
|
|
69
|
+
<button type="button"
|
|
70
|
+
onClick={onShowSave}
|
|
71
|
+
className="flex items-center gap-1 rounded-md px-2 py-1 text-[11px] text-[var(--text-muted)] transition-colors hover:bg-[var(--bg-elevated)] hover:text-[var(--text-secondary)]"
|
|
72
|
+
>
|
|
73
|
+
<Save className="size-3" />
|
|
74
|
+
Save as
|
|
75
|
+
</button>
|
|
76
|
+
)}
|
|
77
|
+
|
|
78
|
+
{hasOverrides && (
|
|
79
|
+
<button type="button"
|
|
80
|
+
onClick={onReset}
|
|
81
|
+
className="ml-auto flex items-center gap-1 rounded-md px-2 py-1 text-[11px] text-[var(--text-muted)] transition-colors hover:bg-[var(--bg-elevated)] hover:text-[var(--text-secondary)]"
|
|
82
|
+
>
|
|
83
|
+
<RotateCcw className="size-3" />
|
|
84
|
+
Reset
|
|
85
|
+
</button>
|
|
86
|
+
)}
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
{showSaveInput && (
|
|
90
|
+
<SavePresetInput onSave={onSave} onCancel={onCancelSave} />
|
|
91
|
+
)}
|
|
92
|
+
</>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Sparkles } from 'lucide-react';
|
|
2
|
+
import type { ContextSkillInfo } from '@sero-ai/common';
|
|
3
|
+
import { CapabilitySection } from './CapabilitySection';
|
|
4
|
+
|
|
5
|
+
interface SkillsSectionProps {
|
|
6
|
+
items: ContextSkillInfo[];
|
|
7
|
+
allDisabled: boolean;
|
|
8
|
+
enabledCount: number;
|
|
9
|
+
isEnabled: (name: string) => boolean;
|
|
10
|
+
onToggle: (name: string) => void;
|
|
11
|
+
onToggleAll: (disabled: boolean) => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function SkillsSection({
|
|
15
|
+
items,
|
|
16
|
+
allDisabled,
|
|
17
|
+
enabledCount,
|
|
18
|
+
isEnabled,
|
|
19
|
+
onToggle,
|
|
20
|
+
onToggleAll,
|
|
21
|
+
}: SkillsSectionProps) {
|
|
22
|
+
return (
|
|
23
|
+
<CapabilitySection
|
|
24
|
+
icon={Sparkles}
|
|
25
|
+
title="Skills"
|
|
26
|
+
tint="violet"
|
|
27
|
+
includeAllLabel="Include all skills"
|
|
28
|
+
emptyLabel="No skills available"
|
|
29
|
+
items={items}
|
|
30
|
+
allDisabled={allDisabled}
|
|
31
|
+
enabledCount={enabledCount}
|
|
32
|
+
isEnabled={isEnabled}
|
|
33
|
+
onToggle={onToggle}
|
|
34
|
+
onToggleAll={onToggleAll}
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { FileText } from 'lucide-react';
|
|
2
|
+
import { ContextSection } from './parts';
|
|
3
|
+
|
|
4
|
+
export interface SystemPromptCopy {
|
|
5
|
+
/** Section title. Defaults to "System Prompt". */
|
|
6
|
+
title?: string;
|
|
7
|
+
/** Help text when no override is set. */
|
|
8
|
+
defaultHint?: string;
|
|
9
|
+
/** Help text when the prompt is set to empty string. */
|
|
10
|
+
emptyHint?: string;
|
|
11
|
+
/** Help text when a custom prompt is set. */
|
|
12
|
+
customHint?: string;
|
|
13
|
+
/** Textarea placeholder. */
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
/** Footer note under the textarea. */
|
|
16
|
+
footnote?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const DEFAULT_COPY: Required<SystemPromptCopy> = {
|
|
20
|
+
title: 'System Prompt',
|
|
21
|
+
defaultHint: 'Using the default system prompt',
|
|
22
|
+
emptyHint: 'System prompt excluded',
|
|
23
|
+
customHint: 'Using a custom system prompt',
|
|
24
|
+
placeholder: 'Enter system prompt...',
|
|
25
|
+
footnote: 'Leave the prompt blank to exclude it entirely, or reset to use the default.',
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
interface SystemPromptSectionProps {
|
|
29
|
+
displayedPrompt: string;
|
|
30
|
+
systemPrompt: string | null;
|
|
31
|
+
onSystemPromptChange: (value: string | null) => void;
|
|
32
|
+
copy?: SystemPromptCopy;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function SystemPromptSection({
|
|
36
|
+
displayedPrompt,
|
|
37
|
+
systemPrompt,
|
|
38
|
+
onSystemPromptChange,
|
|
39
|
+
copy,
|
|
40
|
+
}: SystemPromptSectionProps) {
|
|
41
|
+
const c = { ...DEFAULT_COPY, ...copy };
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<ContextSection
|
|
45
|
+
icon={FileText}
|
|
46
|
+
title={c.title}
|
|
47
|
+
tint="blue"
|
|
48
|
+
badge={
|
|
49
|
+
systemPrompt !== null
|
|
50
|
+
? (systemPrompt === '' ? 'excluded' : 'custom')
|
|
51
|
+
: undefined
|
|
52
|
+
}
|
|
53
|
+
badgeVariant={
|
|
54
|
+
systemPrompt !== null
|
|
55
|
+
? (systemPrompt === '' ? 'disabled' : 'modified')
|
|
56
|
+
: 'default'
|
|
57
|
+
}
|
|
58
|
+
defaultOpen={false}
|
|
59
|
+
>
|
|
60
|
+
<div className="space-y-2">
|
|
61
|
+
<div className="flex items-center justify-between">
|
|
62
|
+
<span className="text-[10px] text-[var(--text-muted)]">
|
|
63
|
+
{systemPrompt === null
|
|
64
|
+
? c.defaultHint
|
|
65
|
+
: systemPrompt === ''
|
|
66
|
+
? c.emptyHint
|
|
67
|
+
: c.customHint}
|
|
68
|
+
</span>
|
|
69
|
+
{systemPrompt !== null && (
|
|
70
|
+
<button type="button"
|
|
71
|
+
onClick={() => onSystemPromptChange(null)}
|
|
72
|
+
className="text-[10px] text-[var(--text-muted)] transition-colors hover:text-[var(--text-secondary)]"
|
|
73
|
+
>
|
|
74
|
+
Reset to default
|
|
75
|
+
</button>
|
|
76
|
+
)}
|
|
77
|
+
</div>
|
|
78
|
+
<textarea aria-label="System prompt"
|
|
79
|
+
value={displayedPrompt}
|
|
80
|
+
onChange={(event) => onSystemPromptChange(event.target.value)}
|
|
81
|
+
className="h-80 w-full resize-y rounded-md border border-border/30 bg-[var(--bg-base)] p-2 font-mono text-[11px] text-[var(--text-secondary)] placeholder:text-[var(--text-muted)] outline-none focus:border-[var(--accent-primary)]"
|
|
82
|
+
placeholder={c.placeholder}
|
|
83
|
+
/>
|
|
84
|
+
<p className="text-[10px] text-[var(--text-muted)]">{c.footnote}</p>
|
|
85
|
+
</div>
|
|
86
|
+
</ContextSection>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Wrench } from 'lucide-react';
|
|
2
|
+
import type { ContextToolInfo } from '@sero-ai/common';
|
|
3
|
+
import { CapabilitySection } from './CapabilitySection';
|
|
4
|
+
|
|
5
|
+
interface ToolsSectionProps {
|
|
6
|
+
items: ContextToolInfo[];
|
|
7
|
+
allDisabled: boolean;
|
|
8
|
+
enabledCount: number;
|
|
9
|
+
isEnabled: (name: string) => boolean;
|
|
10
|
+
onToggle: (name: string) => void;
|
|
11
|
+
onToggleAll: (disabled: boolean) => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function ToolsSection({
|
|
15
|
+
items,
|
|
16
|
+
allDisabled,
|
|
17
|
+
enabledCount,
|
|
18
|
+
isEnabled,
|
|
19
|
+
onToggle,
|
|
20
|
+
onToggleAll,
|
|
21
|
+
}: ToolsSectionProps) {
|
|
22
|
+
return (
|
|
23
|
+
<CapabilitySection
|
|
24
|
+
icon={Wrench}
|
|
25
|
+
title="Tools"
|
|
26
|
+
tint="amber"
|
|
27
|
+
includeAllLabel="Include all tools"
|
|
28
|
+
emptyLabel="No tools available"
|
|
29
|
+
items={items}
|
|
30
|
+
allDisabled={allDisabled}
|
|
31
|
+
enabledCount={enabledCount}
|
|
32
|
+
isEnabled={isEnabled}
|
|
33
|
+
onToggle={onToggle}
|
|
34
|
+
onToggleAll={onToggleAll}
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { ContextEditor, type ContextEditorProps } from './ContextEditor';
|
|
2
|
+
export {
|
|
3
|
+
useContextEditorModel,
|
|
4
|
+
type ContextEditorModel,
|
|
5
|
+
type UseContextEditorModelParams,
|
|
6
|
+
} from './use-context-editor-model';
|
|
7
|
+
export { type SystemPromptCopy } from './SystemPromptSection';
|