@geminilight/mindos 0.6.29 → 0.6.31
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 +10 -4
- package/README_zh.md +10 -4
- package/app/app/api/acp/config/route.ts +82 -0
- package/app/app/api/acp/detect/route.ts +71 -48
- package/app/app/api/acp/install/route.ts +51 -0
- package/app/app/api/acp/session/route.ts +141 -11
- package/app/app/api/ask/route.ts +126 -18
- package/app/app/api/export/route.ts +105 -0
- package/app/app/api/workflows/route.ts +156 -0
- package/app/app/globals.css +2 -2
- package/app/app/page.tsx +7 -2
- package/app/app/trash/page.tsx +7 -0
- package/app/app/view/[...path]/ViewPageClient.tsx +234 -2
- package/app/components/ActivityBar.tsx +12 -4
- package/app/components/AskModal.tsx +4 -1
- package/app/components/ExportModal.tsx +220 -0
- package/app/components/FileTree.tsx +42 -11
- package/app/components/HomeContent.tsx +92 -20
- package/app/components/MarkdownView.tsx +45 -10
- package/app/components/Panel.tsx +1 -0
- package/app/components/RightAskPanel.tsx +5 -1
- package/app/components/Sidebar.tsx +10 -1
- package/app/components/SidebarLayout.tsx +6 -0
- package/app/components/TrashPageClient.tsx +263 -0
- package/app/components/agents/AgentDetailContent.tsx +263 -47
- package/app/components/agents/AgentsContentPage.tsx +11 -0
- package/app/components/agents/AgentsPanelA2aTab.tsx +285 -46
- package/app/components/agents/AgentsPanelSessionsTab.tsx +166 -0
- package/app/components/agents/agents-content-model.ts +2 -2
- package/app/components/ask/AgentSelectorCapsule.tsx +218 -0
- package/app/components/ask/AskContent.tsx +197 -239
- package/app/components/ask/FileChip.tsx +82 -17
- package/app/components/ask/MentionPopover.tsx +21 -3
- package/app/components/ask/MessageList.tsx +30 -9
- package/app/components/ask/SlashCommandPopover.tsx +21 -3
- package/app/components/ask/ToolCallBlock.tsx +102 -18
- package/app/components/changes/ChangesContentPage.tsx +58 -14
- package/app/components/explore/ExploreContent.tsx +4 -7
- package/app/components/explore/UseCaseCard.tsx +18 -1
- package/app/components/explore/use-cases.generated.ts +76 -0
- package/app/components/explore/use-cases.yaml +185 -0
- package/app/components/panels/AgentsPanel.tsx +1 -0
- package/app/components/panels/AgentsPanelHubNav.tsx +9 -2
- package/app/components/panels/DiscoverPanel.tsx +1 -1
- package/app/components/panels/WorkflowsPanel.tsx +206 -0
- package/app/components/renderers/workflow-yaml/StepEditor.tsx +164 -0
- package/app/components/renderers/workflow-yaml/WorkflowEditor.tsx +211 -0
- package/app/components/renderers/workflow-yaml/WorkflowRunner.tsx +269 -0
- package/app/components/renderers/workflow-yaml/WorkflowYamlRenderer.tsx +126 -0
- package/app/components/renderers/workflow-yaml/execution.ts +229 -0
- package/app/components/renderers/workflow-yaml/index.ts +6 -0
- package/app/components/renderers/workflow-yaml/manifest.ts +21 -0
- package/app/components/renderers/workflow-yaml/parser.ts +172 -0
- package/app/components/renderers/workflow-yaml/selectors.tsx +574 -0
- package/app/components/renderers/workflow-yaml/serializer.ts +56 -0
- package/app/components/renderers/workflow-yaml/types.ts +46 -0
- package/app/components/settings/AiTab.tsx +191 -174
- package/app/components/settings/AppearanceTab.tsx +168 -77
- package/app/components/settings/KnowledgeTab.tsx +131 -136
- package/app/components/settings/McpTab.tsx +11 -11
- package/app/components/settings/Primitives.tsx +60 -0
- package/app/components/settings/SettingsContent.tsx +15 -8
- package/app/components/settings/SyncTab.tsx +12 -12
- package/app/components/settings/UninstallTab.tsx +8 -18
- package/app/components/settings/UpdateTab.tsx +82 -82
- package/app/components/settings/types.ts +17 -8
- package/app/hooks/useAcpConfig.ts +96 -0
- package/app/hooks/useAcpDetection.ts +69 -14
- package/app/hooks/useAcpRegistry.ts +46 -11
- package/app/hooks/useAskModal.ts +12 -5
- package/app/hooks/useAskPanel.ts +8 -5
- package/app/hooks/useAskSession.ts +19 -2
- package/app/hooks/useImageUpload.ts +152 -0
- package/app/lib/acp/acp-tools.ts +3 -1
- package/app/lib/acp/agent-descriptors.ts +274 -0
- package/app/lib/acp/bridge.ts +6 -0
- package/app/lib/acp/index.ts +20 -4
- package/app/lib/acp/registry.ts +74 -7
- package/app/lib/acp/session.ts +490 -28
- package/app/lib/acp/subprocess.ts +307 -21
- package/app/lib/acp/types.ts +158 -20
- package/app/lib/actions.ts +57 -3
- package/app/lib/agent/model.ts +18 -3
- package/app/lib/agent/stream-consumer.ts +18 -0
- package/app/lib/agent/to-agent-messages.ts +25 -2
- package/app/lib/agent/tools.ts +56 -9
- package/app/lib/core/export.ts +116 -0
- package/app/lib/core/trash.ts +241 -0
- package/app/lib/fs.ts +47 -0
- package/app/lib/hooks/usePinnedFiles.ts +90 -0
- package/app/lib/i18n/generated/explore-i18n.generated.ts +138 -0
- package/app/lib/i18n/index.ts +3 -0
- package/app/lib/i18n/modules/knowledge.ts +124 -6
- package/app/lib/i18n/modules/navigation.ts +2 -0
- package/app/lib/i18n/modules/onboarding.ts +2 -134
- package/app/lib/i18n/modules/panels.ts +146 -2
- package/app/lib/i18n/modules/settings.ts +12 -0
- package/app/lib/pi-integration/skills.ts +21 -6
- package/app/lib/renderers/index.ts +2 -2
- package/app/lib/settings.ts +10 -0
- package/app/lib/types.ts +12 -1
- package/app/next-env.d.ts +1 -1
- package/app/package.json +11 -3
- package/app/scripts/generate-explore.ts +145 -0
- package/package.json +1 -1
- package/templates/en/.mindos/workflows/Sprint Release.flow.yaml +130 -0
- package/templates/zh/.mindos/workflows//345/221/250/350/277/255/344/273/243/346/243/200/346/237/245.flow.yaml +84 -0
- package/app/components/explore/use-cases.ts +0 -58
- package/app/components/renderers/workflow/WorkflowRenderer.tsx +0 -409
- package/app/components/renderers/workflow/manifest.ts +0 -14
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState, useRef, useEffect, useCallback } from 'react';
|
|
4
|
+
import { createPortal } from 'react-dom';
|
|
5
|
+
import { Bot, ChevronDown, X, Check } from 'lucide-react';
|
|
6
|
+
import type { AcpAgentSelection } from '@/hooks/useAskModal';
|
|
7
|
+
import type { DetectedAgent } from '@/hooks/useAcpDetection';
|
|
8
|
+
import { useLocale } from '@/lib/LocaleContext';
|
|
9
|
+
|
|
10
|
+
interface AgentSelectorCapsuleProps {
|
|
11
|
+
selectedAgent: AcpAgentSelection | null;
|
|
12
|
+
onSelect: (agent: AcpAgentSelection | null) => void;
|
|
13
|
+
installedAgents: DetectedAgent[];
|
|
14
|
+
loading?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface DropdownPos {
|
|
18
|
+
top: number;
|
|
19
|
+
left: number;
|
|
20
|
+
direction: 'up' | 'down';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default function AgentSelectorCapsule({
|
|
24
|
+
selectedAgent,
|
|
25
|
+
onSelect,
|
|
26
|
+
installedAgents,
|
|
27
|
+
loading = false,
|
|
28
|
+
}: AgentSelectorCapsuleProps) {
|
|
29
|
+
const { t } = useLocale();
|
|
30
|
+
const p = t.panels.agents;
|
|
31
|
+
const [open, setOpen] = useState(false);
|
|
32
|
+
const [pos, setPos] = useState<DropdownPos | null>(null);
|
|
33
|
+
const triggerRef = useRef<HTMLButtonElement>(null);
|
|
34
|
+
const dropdownRef = useRef<HTMLDivElement>(null);
|
|
35
|
+
|
|
36
|
+
// Position the dropdown relative to the trigger, rendered via portal
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (!open || !triggerRef.current) return;
|
|
39
|
+
const rect = triggerRef.current.getBoundingClientRect();
|
|
40
|
+
const spaceAbove = rect.top;
|
|
41
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
42
|
+
const estimatedH = 200; // approximate dropdown height
|
|
43
|
+
const direction: 'up' | 'down' = spaceAbove > spaceBelow && spaceAbove > estimatedH ? 'up' : 'down';
|
|
44
|
+
|
|
45
|
+
setPos({
|
|
46
|
+
left: rect.left,
|
|
47
|
+
top: direction === 'up' ? rect.top - 6 : rect.bottom + 6,
|
|
48
|
+
direction,
|
|
49
|
+
});
|
|
50
|
+
}, [open]);
|
|
51
|
+
|
|
52
|
+
// Close dropdown on outside click
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
if (!open) return;
|
|
55
|
+
const handler = (e: MouseEvent) => {
|
|
56
|
+
const target = e.target as Node;
|
|
57
|
+
if (
|
|
58
|
+
triggerRef.current && !triggerRef.current.contains(target) &&
|
|
59
|
+
dropdownRef.current && !dropdownRef.current.contains(target)
|
|
60
|
+
) {
|
|
61
|
+
setOpen(false);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
document.addEventListener('mousedown', handler);
|
|
65
|
+
return () => document.removeEventListener('mousedown', handler);
|
|
66
|
+
}, [open]);
|
|
67
|
+
|
|
68
|
+
// Close on Escape
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
if (!open) return;
|
|
71
|
+
const handler = (e: KeyboardEvent) => {
|
|
72
|
+
if (e.key === 'Escape') setOpen(false);
|
|
73
|
+
};
|
|
74
|
+
document.addEventListener('keydown', handler);
|
|
75
|
+
return () => document.removeEventListener('keydown', handler);
|
|
76
|
+
}, [open]);
|
|
77
|
+
|
|
78
|
+
// Reposition on scroll/resize while open
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
if (!open || !triggerRef.current) return;
|
|
81
|
+
const reposition = () => {
|
|
82
|
+
if (!triggerRef.current) return;
|
|
83
|
+
const rect = triggerRef.current.getBoundingClientRect();
|
|
84
|
+
const spaceAbove = rect.top;
|
|
85
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
86
|
+
const estimatedH = 200;
|
|
87
|
+
const direction: 'up' | 'down' = spaceAbove > spaceBelow && spaceAbove > estimatedH ? 'up' : 'down';
|
|
88
|
+
setPos({
|
|
89
|
+
left: rect.left,
|
|
90
|
+
top: direction === 'up' ? rect.top - 6 : rect.bottom + 6,
|
|
91
|
+
direction,
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
window.addEventListener('scroll', reposition, true);
|
|
95
|
+
window.addEventListener('resize', reposition);
|
|
96
|
+
return () => {
|
|
97
|
+
window.removeEventListener('scroll', reposition, true);
|
|
98
|
+
window.removeEventListener('resize', reposition);
|
|
99
|
+
};
|
|
100
|
+
}, [open]);
|
|
101
|
+
|
|
102
|
+
const handleSelectDefault = useCallback(() => {
|
|
103
|
+
onSelect(null);
|
|
104
|
+
setOpen(false);
|
|
105
|
+
}, [onSelect]);
|
|
106
|
+
|
|
107
|
+
const handleSelectAgent = useCallback((agent: DetectedAgent) => {
|
|
108
|
+
onSelect({ id: agent.id, name: agent.name });
|
|
109
|
+
setOpen(false);
|
|
110
|
+
}, [onSelect]);
|
|
111
|
+
|
|
112
|
+
const handleClear = useCallback((e: React.MouseEvent) => {
|
|
113
|
+
e.stopPropagation();
|
|
114
|
+
onSelect(null);
|
|
115
|
+
}, [onSelect]);
|
|
116
|
+
|
|
117
|
+
const isDefault = !selectedAgent;
|
|
118
|
+
const displayName = selectedAgent?.name ?? p.acpDefaultAgent;
|
|
119
|
+
|
|
120
|
+
// Only show if there are installed agents to choose from
|
|
121
|
+
if (!loading && installedAgents.length === 0 && !selectedAgent) return null;
|
|
122
|
+
|
|
123
|
+
const dropdown = open && pos ? (
|
|
124
|
+
<div
|
|
125
|
+
ref={dropdownRef}
|
|
126
|
+
role="listbox"
|
|
127
|
+
aria-label={p.acpSelectAgent}
|
|
128
|
+
className="fixed z-50 min-w-[180px] max-w-[240px] rounded-lg border border-border bg-card shadow-lg py-1 animate-in fade-in-0 zoom-in-95 duration-100"
|
|
129
|
+
style={{
|
|
130
|
+
left: pos.left,
|
|
131
|
+
...(pos.direction === 'up'
|
|
132
|
+
? { bottom: window.innerHeight - pos.top }
|
|
133
|
+
: { top: pos.top }),
|
|
134
|
+
}}
|
|
135
|
+
>
|
|
136
|
+
{/* Default MindOS Agent option */}
|
|
137
|
+
<button
|
|
138
|
+
type="button"
|
|
139
|
+
role="option"
|
|
140
|
+
aria-selected={isDefault}
|
|
141
|
+
onClick={handleSelectDefault}
|
|
142
|
+
className="flex w-full items-center gap-2 px-3 py-1.5 text-xs text-left transition-colors hover:bg-muted"
|
|
143
|
+
>
|
|
144
|
+
<Bot size={12} className="shrink-0 text-muted-foreground" />
|
|
145
|
+
<span className="flex-1 truncate font-medium">{p.acpDefaultAgent}</span>
|
|
146
|
+
{isDefault && <Check size={11} className="shrink-0 text-[var(--amber)]" />}
|
|
147
|
+
</button>
|
|
148
|
+
|
|
149
|
+
{/* Divider */}
|
|
150
|
+
{installedAgents.length > 0 && (
|
|
151
|
+
<div className="mx-2 my-1 border-t border-border/60" />
|
|
152
|
+
)}
|
|
153
|
+
|
|
154
|
+
{/* Installed ACP agents */}
|
|
155
|
+
{installedAgents.map((agent) => {
|
|
156
|
+
const isSelected = selectedAgent?.id === agent.id;
|
|
157
|
+
return (
|
|
158
|
+
<button
|
|
159
|
+
key={agent.id}
|
|
160
|
+
type="button"
|
|
161
|
+
role="option"
|
|
162
|
+
aria-selected={isSelected}
|
|
163
|
+
onClick={() => handleSelectAgent(agent)}
|
|
164
|
+
className="flex w-full items-center gap-2 px-3 py-1.5 text-xs text-left transition-colors hover:bg-muted"
|
|
165
|
+
>
|
|
166
|
+
<span className="w-2 h-2 rounded-full bg-[var(--success)] shrink-0" />
|
|
167
|
+
<span className="flex-1 truncate">{agent.name}</span>
|
|
168
|
+
{isSelected && <Check size={11} className="shrink-0 text-[var(--amber)]" />}
|
|
169
|
+
</button>
|
|
170
|
+
);
|
|
171
|
+
})}
|
|
172
|
+
</div>
|
|
173
|
+
) : null;
|
|
174
|
+
|
|
175
|
+
return (
|
|
176
|
+
<>
|
|
177
|
+
<button
|
|
178
|
+
ref={triggerRef}
|
|
179
|
+
type="button"
|
|
180
|
+
onClick={() => setOpen(v => !v)}
|
|
181
|
+
className={`
|
|
182
|
+
inline-flex items-center gap-1 rounded-full px-2.5 py-0.5
|
|
183
|
+
text-2xs font-medium transition-colors
|
|
184
|
+
border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring
|
|
185
|
+
${isDefault
|
|
186
|
+
? 'bg-muted/50 border-border/50 text-muted-foreground hover:bg-muted hover:text-foreground'
|
|
187
|
+
: 'bg-[var(--amber)]/10 border-[var(--amber)]/25 text-foreground hover:bg-[var(--amber)]/15'
|
|
188
|
+
}
|
|
189
|
+
`}
|
|
190
|
+
title={p.acpChangeAgent}
|
|
191
|
+
aria-expanded={open}
|
|
192
|
+
aria-haspopup="listbox"
|
|
193
|
+
>
|
|
194
|
+
{isDefault ? (
|
|
195
|
+
<Bot size={11} className="shrink-0 text-muted-foreground" />
|
|
196
|
+
) : (
|
|
197
|
+
<span className="w-1.5 h-1.5 rounded-full bg-[var(--success)] shrink-0" />
|
|
198
|
+
)}
|
|
199
|
+
<span className="truncate max-w-[120px]">{displayName}</span>
|
|
200
|
+
{selectedAgent ? (
|
|
201
|
+
<span
|
|
202
|
+
role="button"
|
|
203
|
+
tabIndex={0}
|
|
204
|
+
onClick={handleClear}
|
|
205
|
+
onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); handleClear(e as unknown as React.MouseEvent); } }}
|
|
206
|
+
className="p-0.5 -mr-1 rounded-full text-muted-foreground hover:text-foreground transition-colors"
|
|
207
|
+
aria-label={`Remove ${selectedAgent.name}`}
|
|
208
|
+
>
|
|
209
|
+
<X size={9} />
|
|
210
|
+
</span>
|
|
211
|
+
) : (
|
|
212
|
+
<ChevronDown size={10} className="shrink-0 text-muted-foreground" />
|
|
213
|
+
)}
|
|
214
|
+
</button>
|
|
215
|
+
{typeof document !== 'undefined' && dropdown && createPortal(dropdown, document.body)}
|
|
216
|
+
</>
|
|
217
|
+
);
|
|
218
|
+
}
|