- Connect your {toolkit.name} account through Composio's hosted authorization
- flow. We'll open a browser window, you approve access there, and this app will
- detect the connection automatically.
+ Connect your {toolkit.name} account. We'll open a browser window, you approve
+ access there, and this app will detect the connection automatically.
-
- Provider access
-
{toolkit.name} can expose{' '}
{toolkit.permissionLabel}. After you connect,
@@ -501,7 +491,7 @@ function ScopeToggles({ scopes, savingScope, onToggle, error }: ScopeTogglesProp
- OpenHuman agent permissions
+ Permissions
Read + Write enabled by default
diff --git a/app/src/components/composio/toolkitMeta.tsx b/app/src/components/composio/toolkitMeta.tsx
index e5b17c7d9..7127e8294 100644
--- a/app/src/components/composio/toolkitMeta.tsx
+++ b/app/src/components/composio/toolkitMeta.tsx
@@ -143,7 +143,7 @@ const MANAGED_COMPOSIO_TOOLKITS: readonly ManagedToolkitEntry[] = Object.freeze(
{ slug: 'typeform', name: 'Typeform' },
{ slug: 'wakatime', name: 'WakaTime' },
{ slug: 'webex', name: 'Webex' },
- { slug: 'whatsapp', name: 'WhatsApp' },
+ { slug: 'whatsapp', name: 'WhatsApp Business' },
{ slug: 'wrike', name: 'Wrike' },
{ slug: 'yandex', name: 'Yandex' },
{ slug: 'ynab', name: 'YNAB' },
@@ -286,7 +286,7 @@ function defaultDescription(name: string, category: SkillCategory): string {
case 'Platform':
return `Connect ${name} for developer, platform, CRM, and business system workflows.`;
default:
- return `Connect ${name} through Composio managed auth.`;
+ return `Connect ${name}.`;
}
}
diff --git a/app/src/components/skills/skillIcons.tsx b/app/src/components/skills/skillIcons.tsx
index 7f76be9d8..9d934c2e9 100644
--- a/app/src/components/skills/skillIcons.tsx
+++ b/app/src/components/skills/skillIcons.tsx
@@ -1,6 +1,7 @@
import type { ReactNode } from 'react';
import type { IconType } from 'react-icons';
import { FaDiscord, FaGlobe, FaTelegramPlane } from 'react-icons/fa';
+import { IoChatbubble } from 'react-icons/io5';
import {
LuBlocks,
LuBot,
@@ -72,6 +73,14 @@ export const CHANNEL_ICONS: Record = {
iconClassName="text-stone-600"
/>
),
+ imessage: (
+
+ ),
};
const CATEGORY_META: Record<
diff --git a/app/src/hooks/useUsageState.ts b/app/src/hooks/useUsageState.ts
index 0b9cb0137..d3601e083 100644
--- a/app/src/hooks/useUsageState.ts
+++ b/app/src/hooks/useUsageState.ts
@@ -77,24 +77,24 @@ export function useUsageState(): UsageState {
const isFreeTier = currentTier === 'FREE';
const usagePct10h =
- teamUsage && teamUsage.fiveHourCapUsd > 0
+ teamUsage && teamUsage.fiveHourCapUsd > 0.01
? Math.min(1, teamUsage.cycleLimit5hr / teamUsage.fiveHourCapUsd)
: 0;
const usagePct7d =
- teamUsage && teamUsage.cycleBudgetUsd > 0
+ teamUsage && teamUsage.cycleBudgetUsd > 0.01
? Math.min(1, (teamUsage.cycleBudgetUsd - teamUsage.remainingUsd) / teamUsage.cycleBudgetUsd)
: 0;
const isBudgetExhausted = teamUsage
- ? teamUsage.cycleBudgetUsd > 0 && teamUsage.remainingUsd <= 0
+ ? teamUsage.cycleBudgetUsd > 0.01 && teamUsage.remainingUsd <= 0.01
: false;
// Some users have no included recurring budget at all. They still need the
// completed-budget warning in chat even though they are not in an exhausted
// paid cycle.
const shouldShowBudgetCompletedMessage = teamUsage
- ? isBudgetExhausted || (teamUsage.cycleBudgetUsd <= 0 && teamUsage.remainingUsd <= 0)
+ ? isBudgetExhausted || (teamUsage.cycleBudgetUsd <= 0.01 && teamUsage.remainingUsd <= 0.01)
: false;
const isRateLimited =
diff --git a/app/src/pages/Home.tsx b/app/src/pages/Home.tsx
index 64061f392..6c4cfc0fe 100644
--- a/app/src/pages/Home.tsx
+++ b/app/src/pages/Home.tsx
@@ -45,7 +45,7 @@ const Home = () => {
const promoCredits = user?.usage?.promotionBalanceUsd ?? 0;
const isFreeTier =
user?.subscription?.plan === 'FREE' || !user?.subscription?.hasActiveSubscription;
- const showPromoBanner = isFreeTier && promoCredits > 0;
+ const showPromoBanner = isFreeTier && promoCredits > 0.01;
const welcomeVariants = useMemo(
() => [`Welcome, ${userName} 👋`, `Let's cook, ${userName} 🧑🍳.`, `Time to Zone In 🧘🏻`],
diff --git a/app/src/pages/Skills.tsx b/app/src/pages/Skills.tsx
index b663f339d..1da43cbf3 100644
--- a/app/src/pages/Skills.tsx
+++ b/app/src/pages/Skills.tsx
@@ -8,7 +8,6 @@ import {
type ComposioToolkitMeta,
KNOWN_COMPOSIO_TOOLKITS,
} from '../components/composio/toolkitMeta';
-import ConnectionBadge, { isMessagingId } from '../components/ConnectionBadge';
import { ToastContainer } from '../components/intelligence/Toast';
import AutocompleteSetupModal from '../components/skills/AutocompleteSetupModal';
import CreateSkillModal from '../components/skills/CreateSkillModal';
@@ -41,19 +40,6 @@ import type { ToastNotification } from '../types/intelligence';
import { IS_DEV } from '../utils/config';
import { subconsciousEscalationsDismiss } from '../utils/tauriCommands';
-function channelStatusDot(status: ChannelConnectionStatus): string {
- switch (status) {
- case 'connected':
- return 'bg-sage-500';
- case 'connecting':
- return 'bg-amber-500 animate-pulse';
- case 'error':
- return 'bg-coral-500';
- default:
- return 'bg-stone-300';
- }
-}
-
function channelStatusLabel(status: ChannelConnectionStatus): string {
switch (status) {
case 'connected':
@@ -84,19 +70,6 @@ function channelStatusColor(status: ChannelConnectionStatus): string {
// Reuse the same dot/label/color vocabulary as the channel cards so the
// "Integrations" section sits visually flush with the rest of the grid.
-function composioStatusDot(connection: ComposioConnection | undefined): string {
- switch (deriveComposioState(connection)) {
- case 'connected':
- return 'bg-sage-500';
- case 'pending':
- return 'bg-amber-500 animate-pulse';
- case 'error':
- return 'bg-coral-500';
- default:
- return 'bg-stone-300';
- }
-}
-
function composioStatusLabel(connection: ComposioConnection | undefined): string {
switch (deriveComposioState(connection)) {
case 'connected':
@@ -106,7 +79,7 @@ function composioStatusLabel(connection: ComposioConnection | undefined): string
case 'error':
return 'Error';
default:
- return 'Not connected';
+ return '';
}
}
@@ -182,7 +155,7 @@ function ComposioConnectorTile({
onClick={handleClick}
title={`${meta.name} — ${meta.description}`}
aria-label={`${meta.name}, ${statusLabel}. ${ctaLabel}.`}
- className={`group flex flex-col items-center gap-2 rounded-2xl border p-3 pb-3 text-center transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/40 ${
+ className={`group flex flex-col justify-center items-center rounded-2xl border p-3 text-center transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/40 ${
isConnected
? 'border-sage-300 bg-sage-50/80 shadow-[0_0_0_1px_rgba(34,197,94,0.12)] hover:bg-sage-50'
: isPending
@@ -193,14 +166,8 @@ function ComposioConnectorTile({
}`}>