groove-dev 0.26.38 → 0.27.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/CHANGELOG.md +59 -0
- package/CLAUDE.md +24 -19
- package/node_modules/@groove-dev/cli/bin/groove.js +2 -0
- package/node_modules/@groove-dev/cli/package.json +1 -1
- package/node_modules/@groove-dev/cli/src/commands/nuke.js +16 -4
- package/node_modules/@groove-dev/cli/src/commands/stop.js +17 -2
- package/node_modules/@groove-dev/daemon/integrations-registry.json +681 -75
- package/node_modules/@groove-dev/daemon/package.json +1 -1
- package/node_modules/@groove-dev/daemon/src/adaptive.js +23 -25
- package/node_modules/@groove-dev/daemon/src/api.js +346 -22
- package/node_modules/@groove-dev/daemon/src/classifier.js +53 -6
- package/node_modules/@groove-dev/daemon/src/firstrun.js +14 -1
- package/node_modules/@groove-dev/daemon/src/gateways/manager.js +2 -2
- package/node_modules/@groove-dev/daemon/src/index.js +28 -4
- package/node_modules/@groove-dev/daemon/src/integrations.js +215 -14
- package/node_modules/@groove-dev/daemon/src/introducer.js +84 -11
- package/node_modules/@groove-dev/daemon/src/journalist.js +43 -1
- package/node_modules/@groove-dev/daemon/src/lockmanager.js +60 -0
- package/node_modules/@groove-dev/daemon/src/mcp-manager.js +270 -0
- package/node_modules/@groove-dev/daemon/src/memory.js +370 -0
- package/node_modules/@groove-dev/daemon/src/pm.js +1 -1
- package/node_modules/@groove-dev/daemon/src/process.js +141 -9
- package/node_modules/@groove-dev/daemon/src/registry.js +1 -1
- package/node_modules/@groove-dev/daemon/src/rotator.js +334 -31
- package/node_modules/@groove-dev/daemon/src/router.js +43 -0
- package/node_modules/@groove-dev/daemon/src/tokentracker.js +70 -18
- package/node_modules/@groove-dev/daemon/src/validate.js +5 -13
- package/node_modules/@groove-dev/daemon/templates/groove-slides.cjs +306 -0
- package/node_modules/@groove-dev/daemon/test/classifier.test.js +3 -5
- package/node_modules/@groove-dev/daemon/test/lockmanager.test.js +64 -0
- package/node_modules/@groove-dev/daemon/test/memory.test.js +252 -0
- package/node_modules/@groove-dev/daemon/test/rotator.test.js +108 -0
- package/node_modules/@groove-dev/daemon/test/router.test.js +64 -0
- package/node_modules/@groove-dev/daemon/test/slides-engine.test.js +230 -0
- package/node_modules/@groove-dev/daemon/test/tokentracker.test.js +78 -0
- package/node_modules/@groove-dev/gui/dist/assets/index-DjORRpF0.css +1 -0
- package/node_modules/@groove-dev/gui/dist/assets/index-eCrVowF0.js +652 -0
- package/node_modules/@groove-dev/gui/dist/index.html +2 -2
- package/node_modules/@groove-dev/gui/package.json +1 -4
- package/node_modules/@groove-dev/gui/src/components/agents/agent-chat.jsx +26 -17
- package/node_modules/@groove-dev/gui/src/components/agents/agent-config.jsx +22 -1
- package/node_modules/@groove-dev/gui/src/components/agents/agent-feed.jsx +53 -21
- package/node_modules/@groove-dev/gui/src/components/agents/agent-node.jsx +132 -90
- package/node_modules/@groove-dev/gui/src/components/agents/spawn-wizard.jsx +212 -1
- package/node_modules/@groove-dev/gui/src/components/dashboard/cache-ring.jsx +6 -2
- package/node_modules/@groove-dev/gui/src/components/dashboard/intel-panel.jsx +495 -174
- package/node_modules/@groove-dev/gui/src/components/dashboard/kpi-card.jsx +12 -2
- package/node_modules/@groove-dev/gui/src/components/dashboard/team-burn-panel.jsx +55 -0
- package/node_modules/@groove-dev/gui/src/components/layout/activity-bar.jsx +3 -3
- package/node_modules/@groove-dev/gui/src/components/layout/app-shell.jsx +24 -19
- package/node_modules/@groove-dev/gui/src/components/layout/command-palette.jsx +2 -2
- package/node_modules/@groove-dev/gui/src/components/marketplace/integration-wizard.jsx +391 -61
- package/node_modules/@groove-dev/gui/src/components/marketplace/marketplace-card.jsx +29 -7
- package/node_modules/@groove-dev/gui/src/lib/format.js +0 -6
- package/node_modules/@groove-dev/gui/src/lib/hooks/use-dashboard.js +23 -5
- package/node_modules/@groove-dev/gui/src/stores/groove.js +59 -9
- package/node_modules/@groove-dev/gui/src/views/agents.jsx +84 -10
- package/node_modules/@groove-dev/gui/src/views/dashboard.jsx +24 -21
- package/node_modules/@groove-dev/gui/src/views/marketplace.jsx +153 -85
- package/package.json +2 -8
- package/packages/cli/bin/groove.js +2 -0
- package/packages/cli/package.json +1 -1
- package/packages/cli/src/commands/nuke.js +16 -4
- package/packages/cli/src/commands/stop.js +17 -2
- package/packages/daemon/integrations-registry.json +681 -75
- package/packages/daemon/package.json +1 -1
- package/packages/daemon/src/adaptive.js +23 -25
- package/packages/daemon/src/api.js +346 -22
- package/packages/daemon/src/classifier.js +53 -6
- package/packages/daemon/src/firstrun.js +14 -1
- package/packages/daemon/src/gateways/manager.js +2 -2
- package/packages/daemon/src/index.js +28 -4
- package/packages/daemon/src/integrations.js +215 -14
- package/packages/daemon/src/introducer.js +84 -11
- package/packages/daemon/src/journalist.js +43 -1
- package/packages/daemon/src/lockmanager.js +60 -0
- package/packages/daemon/src/mcp-manager.js +270 -0
- package/packages/daemon/src/memory.js +370 -0
- package/packages/daemon/src/pm.js +1 -1
- package/packages/daemon/src/process.js +141 -9
- package/packages/daemon/src/registry.js +1 -1
- package/packages/daemon/src/rotator.js +334 -31
- package/packages/daemon/src/router.js +43 -0
- package/packages/daemon/src/tokentracker.js +70 -18
- package/packages/daemon/src/validate.js +5 -13
- package/packages/daemon/templates/groove-slides.cjs +306 -0
- package/packages/gui/dist/assets/index-DjORRpF0.css +1 -0
- package/packages/gui/dist/assets/index-eCrVowF0.js +652 -0
- package/packages/gui/dist/index.html +2 -2
- package/packages/gui/package.json +1 -4
- package/packages/gui/src/components/agents/agent-chat.jsx +26 -17
- package/packages/gui/src/components/agents/agent-config.jsx +22 -1
- package/packages/gui/src/components/agents/agent-feed.jsx +53 -21
- package/packages/gui/src/components/agents/agent-node.jsx +132 -90
- package/packages/gui/src/components/agents/spawn-wizard.jsx +212 -1
- package/packages/gui/src/components/dashboard/cache-ring.jsx +6 -2
- package/packages/gui/src/components/dashboard/intel-panel.jsx +495 -174
- package/packages/gui/src/components/dashboard/kpi-card.jsx +12 -2
- package/packages/gui/src/components/dashboard/team-burn-panel.jsx +55 -0
- package/packages/gui/src/components/layout/activity-bar.jsx +3 -3
- package/packages/gui/src/components/layout/app-shell.jsx +24 -19
- package/packages/gui/src/components/layout/command-palette.jsx +2 -2
- package/packages/gui/src/components/marketplace/integration-wizard.jsx +391 -61
- package/packages/gui/src/components/marketplace/marketplace-card.jsx +29 -7
- package/packages/gui/src/lib/format.js +0 -6
- package/packages/gui/src/lib/hooks/use-dashboard.js +23 -5
- package/packages/gui/src/stores/groove.js +59 -9
- package/packages/gui/src/views/agents.jsx +84 -10
- package/packages/gui/src/views/dashboard.jsx +24 -21
- package/packages/gui/src/views/marketplace.jsx +153 -85
- package/node_modules/@groove-dev/gui/dist/assets/index-CEFKgLGB.css +0 -1
- package/node_modules/@groove-dev/gui/dist/assets/index-CaKBNWcK.js +0 -638
- package/node_modules/@groove-dev/gui/dist/groove-logo-short.png +0 -0
- package/node_modules/@groove-dev/gui/dist/groove-logo.png +0 -0
- package/node_modules/@groove-dev/gui/public/groove-logo-short.png +0 -0
- package/node_modules/@groove-dev/gui/public/groove-logo.png +0 -0
- package/node_modules/@groove-dev/gui/src/components/ui/dropdown-menu.jsx +0 -60
- package/node_modules/@groove-dev/gui/src/lib/hooks/use-media-query.js +0 -18
- package/node_modules/@radix-ui/react-dropdown-menu/LICENSE +0 -21
- package/node_modules/@radix-ui/react-dropdown-menu/README.md +0 -3
- package/node_modules/@radix-ui/react-dropdown-menu/dist/index.d.mts +0 -97
- package/node_modules/@radix-ui/react-dropdown-menu/dist/index.d.ts +0 -97
- package/node_modules/@radix-ui/react-dropdown-menu/dist/index.js +0 -337
- package/node_modules/@radix-ui/react-dropdown-menu/dist/index.js.map +0 -7
- package/node_modules/@radix-ui/react-dropdown-menu/dist/index.mjs +0 -305
- package/node_modules/@radix-ui/react-dropdown-menu/dist/index.mjs.map +0 -7
- package/node_modules/@radix-ui/react-dropdown-menu/package.json +0 -75
- package/node_modules/@radix-ui/react-popover/LICENSE +0 -21
- package/node_modules/@radix-ui/react-popover/README.md +0 -3
- package/node_modules/@radix-ui/react-popover/dist/index.d.mts +0 -85
- package/node_modules/@radix-ui/react-popover/dist/index.d.ts +0 -85
- package/node_modules/@radix-ui/react-popover/dist/index.js +0 -352
- package/node_modules/@radix-ui/react-popover/dist/index.js.map +0 -7
- package/node_modules/@radix-ui/react-popover/dist/index.mjs +0 -320
- package/node_modules/@radix-ui/react-popover/dist/index.mjs.map +0 -7
- package/node_modules/@radix-ui/react-popover/package.json +0 -82
- package/node_modules/@radix-ui/react-separator/LICENSE +0 -21
- package/node_modules/@radix-ui/react-separator/README.md +0 -3
- package/node_modules/@radix-ui/react-separator/dist/index.d.mts +0 -21
- package/node_modules/@radix-ui/react-separator/dist/index.d.ts +0 -21
- package/node_modules/@radix-ui/react-separator/dist/index.js +0 -65
- package/node_modules/@radix-ui/react-separator/dist/index.js.map +0 -7
- package/node_modules/@radix-ui/react-separator/dist/index.mjs +0 -32
- package/node_modules/@radix-ui/react-separator/dist/index.mjs.map +0 -7
- package/node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive/LICENSE +0 -21
- package/node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive/README.md +0 -3
- package/node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive/dist/index.d.mts +0 -52
- package/node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive/dist/index.d.ts +0 -52
- package/node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive/dist/index.js +0 -80
- package/node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive/dist/index.js.map +0 -7
- package/node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive/dist/index.mjs +0 -47
- package/node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive/dist/index.mjs.map +0 -7
- package/node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive/package.json +0 -69
- package/node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-slot/LICENSE +0 -21
- package/node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-slot/README.md +0 -3
- package/node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-slot/dist/index.d.mts +0 -22
- package/node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-slot/dist/index.d.ts +0 -22
- package/node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-slot/dist/index.js +0 -152
- package/node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-slot/dist/index.js.map +0 -7
- package/node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-slot/dist/index.mjs +0 -119
- package/node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-slot/dist/index.mjs.map +0 -7
- package/node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-slot/package.json +0 -64
- package/node_modules/@radix-ui/react-separator/package.json +0 -69
- package/packages/gui/dist/assets/index-CEFKgLGB.css +0 -1
- package/packages/gui/dist/assets/index-CaKBNWcK.js +0 -638
- package/packages/gui/dist/groove-logo-short.png +0 -0
- package/packages/gui/dist/groove-logo.png +0 -0
- package/packages/gui/public/groove-logo-short.png +0 -0
- package/packages/gui/public/groove-logo.png +0 -0
- package/packages/gui/src/components/ui/dropdown-menu.jsx +0 -60
- package/packages/gui/src/lib/hooks/use-media-query.js +0 -18
|
@@ -11,11 +11,47 @@ import {
|
|
|
11
11
|
Server, Monitor, Code2, TestTube, Cloud, FileText,
|
|
12
12
|
Shield, Database, Megaphone, Calculator, UserCheck,
|
|
13
13
|
Headphones, BarChart3, Rocket, ChevronDown, Pen, Presentation,
|
|
14
|
-
Sparkles, X, Search, AlertTriangle,
|
|
14
|
+
Sparkles, X, Search, AlertTriangle, Plug,
|
|
15
15
|
} from 'lucide-react';
|
|
16
16
|
import { api } from '../../lib/api';
|
|
17
17
|
import { Dialog, DialogContent } from '../ui/dialog';
|
|
18
18
|
|
|
19
|
+
const INTEGRATION_LOGOS = {
|
|
20
|
+
'google-workspace': 'https://cdn.simpleicons.org/google/white',
|
|
21
|
+
github: 'https://cdn.simpleicons.org/github/white',
|
|
22
|
+
stripe: 'https://cdn.simpleicons.org/stripe/635BFF',
|
|
23
|
+
gmail: 'https://cdn.simpleicons.org/gmail/EA4335',
|
|
24
|
+
'google-calendar': 'https://cdn.simpleicons.org/googlecalendar/4285F4',
|
|
25
|
+
'google-drive': 'https://cdn.simpleicons.org/googledrive/4285F4',
|
|
26
|
+
'google-docs': 'https://cdn.simpleicons.org/googledocs/4285F4',
|
|
27
|
+
'google-sheets': 'https://cdn.simpleicons.org/googlesheets/34A853',
|
|
28
|
+
'google-slides': 'https://cdn.simpleicons.org/googleslides/FBBC04',
|
|
29
|
+
'google-maps': 'https://cdn.simpleicons.org/googlemaps/4285F4',
|
|
30
|
+
postgres: 'https://cdn.simpleicons.org/postgresql/4169E1',
|
|
31
|
+
notion: 'https://cdn.simpleicons.org/notion/white',
|
|
32
|
+
linear: 'https://cdn.simpleicons.org/linear/5E6AD2',
|
|
33
|
+
'brave-search': 'https://cdn.simpleicons.org/brave/FB542B',
|
|
34
|
+
'home-assistant': 'https://cdn.simpleicons.org/homeassistant/18BCF2',
|
|
35
|
+
sentry: 'https://cdn.simpleicons.org/sentry/362D59',
|
|
36
|
+
elevenlabs: 'https://cdn.simpleicons.org/elevenlabs/white',
|
|
37
|
+
hubspot: 'https://cdn.simpleicons.org/hubspot/FF7A59',
|
|
38
|
+
jira: 'https://cdn.simpleicons.org/jira/0052CC',
|
|
39
|
+
sendgrid: 'https://cdn.simpleicons.org/sendgrid/1A82E2',
|
|
40
|
+
resend: 'https://cdn.simpleicons.org/resend/white',
|
|
41
|
+
replicate: 'https://cdn.simpleicons.org/replicate/white',
|
|
42
|
+
vercel: 'https://cdn.simpleicons.org/vercel/white',
|
|
43
|
+
supabase: 'https://cdn.simpleicons.org/supabase/3FCF8E',
|
|
44
|
+
mixpanel: 'https://cdn.simpleicons.org/mixpanel/7856FF',
|
|
45
|
+
datadog: 'https://cdn.simpleicons.org/datadog/632CA6',
|
|
46
|
+
airtable: 'https://cdn.simpleicons.org/airtable/18BFFF',
|
|
47
|
+
zendesk: 'https://cdn.simpleicons.org/zendesk/03363D',
|
|
48
|
+
intercom: 'https://cdn.simpleicons.org/intercom/6AFDEF',
|
|
49
|
+
twilio: 'https://cdn.simpleicons.org/twilio/F22F46',
|
|
50
|
+
telnyx: 'https://cdn.simpleicons.org/telnyx/00C08B',
|
|
51
|
+
aws: 'https://cdn.simpleicons.org/amazonaws/FF9900',
|
|
52
|
+
plaid: 'https://cdn.simpleicons.org/plaid/white',
|
|
53
|
+
};
|
|
54
|
+
|
|
19
55
|
const ROLE_PRESETS = [
|
|
20
56
|
{ id: 'planner', label: 'Planner', desc: 'Plans the team and tasks', icon: Rocket, tier: 'Heavy' },
|
|
21
57
|
{ id: 'backend', label: 'Backend', desc: 'APIs, services, databases', icon: Server, tier: 'Medium' },
|
|
@@ -62,6 +98,11 @@ export function SpawnWizard() {
|
|
|
62
98
|
const [selectedSkills, setSelectedSkills] = useState([]);
|
|
63
99
|
const [skillModalOpen, setSkillModalOpen] = useState(false);
|
|
64
100
|
const [skillSearch, setSkillSearch] = useState('');
|
|
101
|
+
const [installedIntegrations, setInstalledIntegrations] = useState([]);
|
|
102
|
+
const [selectedIntegrations, setSelectedIntegrations] = useState([]);
|
|
103
|
+
const [integrationModalOpen, setIntegrationModalOpen] = useState(false);
|
|
104
|
+
const [integrationSearch, setIntegrationSearch] = useState('');
|
|
105
|
+
const [integrationApproval, setIntegrationApproval] = useState('manual');
|
|
65
106
|
const [spawning, setSpawning] = useState(false);
|
|
66
107
|
|
|
67
108
|
useEffect(() => {
|
|
@@ -80,8 +121,13 @@ export function SpawnWizard() {
|
|
|
80
121
|
api.get('/skills/installed').then((data) => {
|
|
81
122
|
setInstalledSkills(Array.isArray(data) ? data : []);
|
|
82
123
|
}).catch(() => {});
|
|
124
|
+
api.get('/integrations/installed').then((data) => {
|
|
125
|
+
setInstalledIntegrations(Array.isArray(data) ? data : []);
|
|
126
|
+
}).catch(() => {});
|
|
83
127
|
setRole(''); setCustomRole(''); setName(''); setProvider(''); setModel(''); setPrompt('');
|
|
84
128
|
setSelectedSkills([]);
|
|
129
|
+
setSelectedIntegrations([]);
|
|
130
|
+
setIntegrationApproval('manual');
|
|
85
131
|
}
|
|
86
132
|
}, [open, fetchProviders]);
|
|
87
133
|
|
|
@@ -101,6 +147,8 @@ export function SpawnWizard() {
|
|
|
101
147
|
...(model && { model }),
|
|
102
148
|
...(prompt && { prompt }),
|
|
103
149
|
...(selectedSkills.length > 0 && { skills: selectedSkills }),
|
|
150
|
+
...(selectedIntegrations.length > 0 && { integrations: selectedIntegrations }),
|
|
151
|
+
...(selectedIntegrations.length > 0 && { integrationApproval }),
|
|
104
152
|
};
|
|
105
153
|
await spawnAgent(config);
|
|
106
154
|
closeDetail();
|
|
@@ -328,6 +376,169 @@ export function SpawnWizard() {
|
|
|
328
376
|
</DialogContent>
|
|
329
377
|
</Dialog>
|
|
330
378
|
|
|
379
|
+
{/* Integrations */}
|
|
380
|
+
<div className="space-y-1.5">
|
|
381
|
+
<label className="text-xs font-medium text-text-2 font-sans">Integrations</label>
|
|
382
|
+
<div className="flex flex-wrap items-center gap-1.5">
|
|
383
|
+
{selectedIntegrations.map((integrationId) => {
|
|
384
|
+
const integration = installedIntegrations.find((i) => i.id === integrationId);
|
|
385
|
+
const logoUrl = INTEGRATION_LOGOS[integrationId];
|
|
386
|
+
return (
|
|
387
|
+
<span
|
|
388
|
+
key={integrationId}
|
|
389
|
+
className="inline-flex items-center gap-1 px-2 py-1 rounded bg-accent/12 text-accent border border-accent/25 text-2xs font-sans"
|
|
390
|
+
>
|
|
391
|
+
{logoUrl ? (
|
|
392
|
+
<img src={logoUrl} alt="" className="w-2.5 h-2.5" />
|
|
393
|
+
) : (
|
|
394
|
+
<Plug size={9} />
|
|
395
|
+
)}
|
|
396
|
+
{integration?.name || integrationId}
|
|
397
|
+
<button
|
|
398
|
+
onClick={() => setSelectedIntegrations((prev) => prev.filter((i) => i !== integrationId))}
|
|
399
|
+
className="ml-0.5 hover:text-text-0 cursor-pointer"
|
|
400
|
+
>
|
|
401
|
+
<X size={9} />
|
|
402
|
+
</button>
|
|
403
|
+
</span>
|
|
404
|
+
);
|
|
405
|
+
})}
|
|
406
|
+
<button
|
|
407
|
+
onClick={() => { setIntegrationModalOpen(true); setIntegrationSearch(''); }}
|
|
408
|
+
className={cn(
|
|
409
|
+
'inline-flex items-center gap-1.5 px-2.5 py-1 rounded text-2xs font-sans transition-colors cursor-pointer',
|
|
410
|
+
'bg-surface-0 text-text-2 border border-border-subtle hover:border-border hover:text-text-0',
|
|
411
|
+
)}
|
|
412
|
+
>
|
|
413
|
+
<Plug size={10} />
|
|
414
|
+
{selectedIntegrations.length > 0 ? 'Add integration' : 'Attach integration'}
|
|
415
|
+
</button>
|
|
416
|
+
</div>
|
|
417
|
+
</div>
|
|
418
|
+
|
|
419
|
+
{/* Integration picker modal */}
|
|
420
|
+
<Dialog open={integrationModalOpen} onOpenChange={setIntegrationModalOpen}>
|
|
421
|
+
<DialogContent title="Select Integration" className="max-w-sm">
|
|
422
|
+
<div className="space-y-3 p-4">
|
|
423
|
+
<div className="relative">
|
|
424
|
+
<Search size={14} className="absolute left-2.5 top-1/2 -translate-y-1/2 text-text-4" />
|
|
425
|
+
<input
|
|
426
|
+
value={integrationSearch}
|
|
427
|
+
onChange={(e) => setIntegrationSearch(e.target.value)}
|
|
428
|
+
placeholder="Search integrations..."
|
|
429
|
+
autoFocus
|
|
430
|
+
className="w-full h-8 pl-8 pr-3 text-xs rounded-md bg-surface-0 border border-border text-text-0 font-sans focus:outline-none focus:ring-1 focus:ring-accent"
|
|
431
|
+
/>
|
|
432
|
+
</div>
|
|
433
|
+
<div className="max-h-64 overflow-y-auto space-y-1">
|
|
434
|
+
{installedIntegrations
|
|
435
|
+
.filter((i) => {
|
|
436
|
+
if (!integrationSearch) return true;
|
|
437
|
+
const q = integrationSearch.toLowerCase();
|
|
438
|
+
return (i.name || i.id).toLowerCase().includes(q) || (i.description || '').toLowerCase().includes(q);
|
|
439
|
+
})
|
|
440
|
+
.map((integration) => {
|
|
441
|
+
const active = selectedIntegrations.includes(integration.id);
|
|
442
|
+
const configured = integration.configured !== false;
|
|
443
|
+
const logoUrl = INTEGRATION_LOGOS[integration.id];
|
|
444
|
+
const roleMatch = selectedRole && Array.isArray(integration.roles) && integration.roles.includes(selectedRole);
|
|
445
|
+
return (
|
|
446
|
+
<button
|
|
447
|
+
key={integration.id}
|
|
448
|
+
onClick={() => {
|
|
449
|
+
if (!configured) return;
|
|
450
|
+
setSelectedIntegrations((prev) =>
|
|
451
|
+
active ? prev.filter((i) => i !== integration.id) : [...prev, integration.id]
|
|
452
|
+
);
|
|
453
|
+
}}
|
|
454
|
+
disabled={!configured}
|
|
455
|
+
className={cn(
|
|
456
|
+
'w-full flex items-center gap-2.5 px-3 py-2 rounded-md text-left transition-colors',
|
|
457
|
+
configured ? 'cursor-pointer' : 'opacity-40 cursor-not-allowed',
|
|
458
|
+
active
|
|
459
|
+
? 'bg-accent/10 border border-accent/25'
|
|
460
|
+
: configured
|
|
461
|
+
? 'hover:bg-surface-3 border border-transparent'
|
|
462
|
+
: 'border border-transparent',
|
|
463
|
+
)}
|
|
464
|
+
>
|
|
465
|
+
{logoUrl ? (
|
|
466
|
+
<img src={logoUrl} alt="" className="w-4 h-4 flex-shrink-0" />
|
|
467
|
+
) : (
|
|
468
|
+
<Plug size={12} className={active ? 'text-accent' : 'text-text-3'} />
|
|
469
|
+
)}
|
|
470
|
+
<div className="flex-1 min-w-0">
|
|
471
|
+
<div className="flex items-center gap-1.5">
|
|
472
|
+
<span className="text-xs font-semibold text-text-0 font-sans truncate">{integration.name || integration.id}</span>
|
|
473
|
+
{!configured && (
|
|
474
|
+
<span className="text-2xs text-text-4 font-sans">(not configured)</span>
|
|
475
|
+
)}
|
|
476
|
+
{configured && roleMatch && (
|
|
477
|
+
<span className="text-2xs font-mono text-accent/70 bg-accent/8 px-1 py-px rounded">
|
|
478
|
+
rec
|
|
479
|
+
</span>
|
|
480
|
+
)}
|
|
481
|
+
</div>
|
|
482
|
+
{integration.description && (
|
|
483
|
+
<div className="text-2xs text-text-3 font-sans truncate">{integration.description}</div>
|
|
484
|
+
)}
|
|
485
|
+
{!configured && (
|
|
486
|
+
<div className="text-2xs text-text-4 font-sans">Configure in Marketplace</div>
|
|
487
|
+
)}
|
|
488
|
+
</div>
|
|
489
|
+
{active && <CheckMark />}
|
|
490
|
+
</button>
|
|
491
|
+
);
|
|
492
|
+
})}
|
|
493
|
+
{installedIntegrations.length === 0 && (
|
|
494
|
+
<div className="text-center py-6 text-xs text-text-3 font-sans">
|
|
495
|
+
No integrations installed. Visit the Marketplace to install integrations.
|
|
496
|
+
</div>
|
|
497
|
+
)}
|
|
498
|
+
</div>
|
|
499
|
+
</div>
|
|
500
|
+
</DialogContent>
|
|
501
|
+
</Dialog>
|
|
502
|
+
|
|
503
|
+
{/* Approval mode */}
|
|
504
|
+
{selectedIntegrations.length > 0 && (
|
|
505
|
+
<div className="space-y-1.5">
|
|
506
|
+
<label className="text-xs font-medium text-text-2 font-sans">Integration Approvals</label>
|
|
507
|
+
<div className="flex gap-1.5">
|
|
508
|
+
<button
|
|
509
|
+
onClick={() => setIntegrationApproval('manual')}
|
|
510
|
+
className={cn(
|
|
511
|
+
'flex-1 flex items-center gap-2 px-3 py-2 rounded-md border text-left transition-all cursor-pointer',
|
|
512
|
+
integrationApproval === 'manual'
|
|
513
|
+
? 'border-accent bg-accent/5'
|
|
514
|
+
: 'border-border-subtle bg-surface-1 hover:border-border',
|
|
515
|
+
)}
|
|
516
|
+
>
|
|
517
|
+
<Shield size={13} className={integrationApproval === 'manual' ? 'text-accent' : 'text-text-3'} />
|
|
518
|
+
<div>
|
|
519
|
+
<div className="text-2xs font-semibold text-text-0 font-sans">Manual</div>
|
|
520
|
+
<div className="text-2xs text-text-3 font-sans">You approve each action</div>
|
|
521
|
+
</div>
|
|
522
|
+
</button>
|
|
523
|
+
<button
|
|
524
|
+
onClick={() => setIntegrationApproval('auto')}
|
|
525
|
+
className={cn(
|
|
526
|
+
'flex-1 flex items-center gap-2 px-3 py-2 rounded-md border text-left transition-all cursor-pointer',
|
|
527
|
+
integrationApproval === 'auto'
|
|
528
|
+
? 'border-warning bg-warning/5'
|
|
529
|
+
: 'border-border-subtle bg-surface-1 hover:border-border',
|
|
530
|
+
)}
|
|
531
|
+
>
|
|
532
|
+
<Sparkles size={13} className={integrationApproval === 'auto' ? 'text-warning' : 'text-text-3'} />
|
|
533
|
+
<div>
|
|
534
|
+
<div className="text-2xs font-semibold text-text-0 font-sans">Auto</div>
|
|
535
|
+
<div className="text-2xs text-text-3 font-sans">Agent acts without asking</div>
|
|
536
|
+
</div>
|
|
537
|
+
</button>
|
|
538
|
+
</div>
|
|
539
|
+
</div>
|
|
540
|
+
)}
|
|
541
|
+
|
|
331
542
|
</div>
|
|
332
543
|
)}
|
|
333
544
|
</div>
|
|
@@ -5,8 +5,12 @@ import { fmtNum } from '../../lib/format';
|
|
|
5
5
|
|
|
6
6
|
const CacheRing = memo(function CacheRing({ cacheRead = 0, cacheCreation = 0, totalInput = 0, size = 140 }) {
|
|
7
7
|
const canvasRef = useRef(null);
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
// Cache hit rate denominator is only cacheable tokens (reads + creation).
|
|
9
|
+
// Fresh inputTokens are conversation turns that were never cache-eligible;
|
|
10
|
+
// including them falsely depresses the rate.
|
|
11
|
+
const cacheable = cacheRead + cacheCreation;
|
|
12
|
+
const total = cacheable; // used only by arc-fill and hit-rate
|
|
13
|
+
const hitRate = cacheable > 0 ? (cacheRead / cacheable) * 100 : 0;
|
|
10
14
|
|
|
11
15
|
useEffect(() => {
|
|
12
16
|
const canvas = canvasRef.current;
|