From 301d08303e9a374492dec7013ad9495b633687fd Mon Sep 17 00:00:00 2001 From: Ajax Davis Date: Sat, 17 Jan 2026 04:18:56 +1000 Subject: [PATCH] feat(agents): add GPT-4.1 models and expandable collections - Add GPT-4.1 and GPT-4.1-mini to OpenAI provider models - Set gpt-4.1-mini as default model for new agents - Make collections in chat tools panel expandable/clickable - Fix type error in ChatToolsPanel --- .../web/src/app/dashboard/agents/new/page.tsx | 2 +- .../src/components/agents/ChatToolsPanel.tsx | 154 ++++++++++++++++-- packages/types/src/agent.ts | 2 + 3 files changed, 142 insertions(+), 16 deletions(-) diff --git a/apps/web/src/app/dashboard/agents/new/page.tsx b/apps/web/src/app/dashboard/agents/new/page.tsx index 2cfdc6f..67eb6ea 100644 --- a/apps/web/src/app/dashboard/agents/new/page.tsx +++ b/apps/web/src/app/dashboard/agents/new/page.tsx @@ -42,7 +42,7 @@ export default function NewAgentPage(): React.ReactElement { uid: '', description: '', provider: 'OPENAI', - modelId: 'gpt-4o', + modelId: 'gpt-4.1-mini', systemPrompt: '', temperature: 0.7, maxToolCallsPerTurn: 20, diff --git a/apps/web/src/components/agents/ChatToolsPanel.tsx b/apps/web/src/components/agents/ChatToolsPanel.tsx index 2b17919..f7da602 100644 --- a/apps/web/src/components/agents/ChatToolsPanel.tsx +++ b/apps/web/src/components/agents/ChatToolsPanel.tsx @@ -2,6 +2,7 @@ import { Button } from '@tpmjs/ui/Button/Button'; import { Icon } from '@tpmjs/ui/Icon/Icon'; +import { useCallback, useState } from 'react'; export interface ToolInfo { id: string; @@ -27,6 +28,12 @@ export interface CollectionInfo { }; } +interface CollectionToolData { + tools: ToolInfo[]; + loading: boolean; + error: string | null; +} + interface ChatToolsPanelProps { tools: ToolInfo[]; collections: CollectionInfo[]; @@ -42,6 +49,63 @@ export function ChatToolsPanel({ onClose, onToolClick, }: ChatToolsPanelProps) { + const [expandedCollections, setExpandedCollections] = useState>(new Set()); + const [collectionTools, setCollectionTools] = useState>({}); + + const fetchCollectionTools = useCallback(async (collectionId: string) => { + const existingData = collectionTools[collectionId]; + if (existingData?.tools && existingData.tools.length > 0) return; + + setCollectionTools((prev) => ({ + ...prev, + [collectionId]: { tools: [], loading: true, error: null }, + })); + + try { + const response = await fetch(`/api/collections/${collectionId}/tools`); + const data = await response.json(); + + if (data.success) { + // Transform the response to match ToolInfo structure + const transformedTools: ToolInfo[] = (data.data || []).map( + (ct: { id: string; toolId: string; tool: ToolInfo['tool'] }) => ({ + id: ct.id, + toolId: ct.toolId, + tool: ct.tool, + }) + ); + setCollectionTools((prev) => ({ + ...prev, + [collectionId]: { tools: transformedTools, loading: false, error: null }, + })); + } else { + setCollectionTools((prev) => ({ + ...prev, + [collectionId]: { tools: [], loading: false, error: data.error || 'Failed to load' }, + })); + } + } catch { + setCollectionTools((prev) => ({ + ...prev, + [collectionId]: { tools: [], loading: false, error: 'Failed to load tools' }, + })); + } + }, [collectionTools]); + + const toggleCollection = (collectionId: string) => { + setExpandedCollections((prev) => { + const next = new Set(prev); + if (next.has(collectionId)) { + next.delete(collectionId); + } else { + next.add(collectionId); + // Fetch tools when expanding + fetchCollectionTools(collectionId); + } + return next; + }); + }; + if (!isOpen) return null; const totalToolsFromCollections = collections.reduce( @@ -106,22 +170,82 @@ export function ChatToolsPanel({ from collections ({totalToolsFromCollections})
- {collections.map((c) => ( -
-
- - - {c.collection.name} - + {collections.map((c) => { + const isExpanded = expandedCollections.has(c.collectionId); + const toolData = collectionTools[c.collectionId]; + + return ( +
+ {/* collection header - clickable */} + + + {/* expanded tools */} + {isExpanded && ( +
+ {toolData?.loading ? ( +
+ + loading... +
+ ) : toolData?.error ? ( +
+ {toolData.error} +
+ ) : toolData?.tools.length === 0 ? ( +
+ no tools in collection +
+ ) : ( +
+ {toolData?.tools.map((t) => ( + + ))} +
+ )} +
+ )}
-

- {c.collection.toolCount} tools -

-
- ))} + ); + })}
)} diff --git a/packages/types/src/agent.ts b/packages/types/src/agent.ts index c0d927f..4ad597e 100644 --- a/packages/types/src/agent.ts +++ b/packages/types/src/agent.ts @@ -237,6 +237,8 @@ export const CONVERSATION_LIMITS = { export const PROVIDER_MODELS = { OPENAI: [ + { id: 'gpt-4.1-mini', name: 'GPT-4.1 Mini', contextWindow: 1000000 }, + { id: 'gpt-4.1', name: 'GPT-4.1', contextWindow: 1000000 }, { id: 'gpt-4o', name: 'GPT-4o', contextWindow: 128000 }, { id: 'gpt-4o-mini', name: 'GPT-4o Mini', contextWindow: 128000 }, { id: 'gpt-4-turbo', name: 'GPT-4 Turbo', contextWindow: 128000 },