Skip to content

Commit 4610c03

Browse files
Claudehotlong
andauthored
Fix agent and tool metadata display in Studio sidebar
- Change AI protocol group to use singular types: 'agent', 'tool', 'ragPipeline' - Add 'tool' type to Studio AI sidebar group - Register all built-in tools as metadata in AI Service Plugin - Update Studio components to support both singular and plural forms - Add Wrench icon for tools in Studio UI - Add tool code export support to CodeExporter Agent-Logs-Url: https://github.com/objectstack-ai/framework/sessions/54384e52-eb4f-4e76-8886-2bd8e1d1cbfd Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 92a5e29 commit 4610c03

6 files changed

Lines changed: 71 additions & 9 deletions

File tree

apps/studio/src/components/CodeExporter.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/com
55
import { Button } from '@/components/ui/button';
66
import { Badge } from '@/components/ui/badge';
77
import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs';
8-
import { Code2, Copy, Check, Database, Layout, Workflow, Bot, AppWindow } from 'lucide-react';
8+
import { Code2, Copy, Check, Database, Layout, Workflow, Bot, AppWindow, Wrench } from 'lucide-react';
99

1010
// ─── Types ──────────────────────────────────────────────────────────
1111

12-
type ExportType = 'object' | 'view' | 'flow' | 'agent' | 'app';
12+
type ExportType = 'object' | 'view' | 'flow' | 'agent' | 'tool' | 'app';
1313

1414
export interface CodeExporterProps {
1515
type: ExportType;
@@ -24,6 +24,7 @@ const TYPE_LABELS: Record<ExportType, { label: string; icon: React.ElementType }
2424
view: { label: 'View', icon: Layout },
2525
flow: { label: 'Flow', icon: Workflow },
2626
agent: { label: 'Agent', icon: Bot },
27+
tool: { label: 'Tool', icon: Wrench },
2728
app: { label: 'App', icon: AppWindow },
2829
};
2930

@@ -135,11 +136,26 @@ function generateAppCode(def: Record<string, unknown>, name?: string): string {
135136
return lines.join('\n');
136137
}
137138

139+
function generateToolCode(def: Record<string, unknown>, name?: string): string {
140+
const toolName = name || (def.name as string) || 'my_tool';
141+
const lines = [
142+
"import { defineStack } from '@objectstack/spec';",
143+
'',
144+
'export default defineStack({',
145+
' tools: {',
146+
` ${toolName}: ${formatValue(def, 2)},`,
147+
' },',
148+
'});',
149+
];
150+
return lines.join('\n');
151+
}
152+
138153
const CODE_GENERATORS: Record<ExportType, (def: Record<string, unknown>, name?: string) => string> = {
139154
object: generateObjectCode,
140155
view: generateViewCode,
141156
flow: generateFlowCode,
142157
agent: generateAgentCode,
158+
tool: generateToolCode,
143159
app: generateAppCode,
144160
};
145161

apps/studio/src/components/MetadataInspector.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { Button } from "@/components/ui/button";
1010
import { ScrollArea } from "@/components/ui/scroll-area";
1111
import {
1212
Search, Copy, Check, ChevronRight, ChevronDown,
13-
Zap, BarChart3, FileText, Workflow, Bot, Globe, BookOpen, Shield,
13+
Zap, BarChart3, FileText, Workflow, Bot, Globe, BookOpen, Shield, Wrench,
1414
type LucideIcon,
1515
} from 'lucide-react';
1616
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
@@ -34,8 +34,12 @@ const TYPE_ICONS: Record<string, LucideIcon> = {
3434
dashboards: BarChart3,
3535
reports: FileText,
3636
flows: Workflow,
37+
agent: Bot,
3738
agents: Bot,
39+
tool: Wrench,
40+
tools: Wrench,
3841
apis: Globe,
42+
ragPipeline: BookOpen,
3943
ragPipelines: BookOpen,
4044
profiles: Shield,
4145
sharingRules: Shield,
@@ -46,8 +50,12 @@ const TYPE_LABELS: Record<string, string> = {
4650
dashboards: 'Dashboard',
4751
reports: 'Report',
4852
flows: 'Flow',
53+
agent: 'Agent',
4954
agents: 'Agent',
55+
tool: 'Tool',
56+
tools: 'Tool',
5057
apis: 'API',
58+
ragPipeline: 'RAG Pipeline',
5159
ragPipelines: 'RAG Pipeline',
5260
profiles: 'Profile',
5361
sharingRules: 'Sharing Rule',

apps/studio/src/components/app-sidebar.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
UserCog,
3333
ChevronRight,
3434
Settings,
35+
Wrench,
3536
type LucideIcon,
3637
} from "lucide-react"
3738
import { useState, useEffect, useCallback, useMemo } from "react"
@@ -94,7 +95,11 @@ const META_TYPE_HINTS: Record<string, { label: string; icon: LucideIcon }> = {
9495
profiles: { label: 'Profiles', icon: Shield },
9596
sharingRules: { label: 'Sharing Rules', icon: Shield },
9697
policies: { label: 'Policies', icon: Shield },
98+
agent: { label: 'Agents', icon: Bot },
9799
agents: { label: 'Agents', icon: Bot },
100+
tool: { label: 'Tools', icon: Wrench },
101+
tools: { label: 'Tools', icon: Wrench },
102+
ragPipeline: { label: 'RAG Pipelines', icon: BookOpen },
98103
ragPipelines: { label: 'RAG Pipelines', icon: BookOpen },
99104
apis: { label: 'APIs', icon: Globe },
100105
connectors: { label: 'Connectors', icon: Link2 },
@@ -123,7 +128,7 @@ const PROTOCOL_GROUPS: ProtocolGroup[] = [
123128
{ key: 'ui', label: 'UI', icon: AppWindow, types: ['app', 'apps', 'actions', 'views', 'pages', 'dashboards', 'reports', 'themes'] },
124129
{ key: 'automation', label: 'Automation', icon: Workflow, types: ['flows', 'workflows', 'approvals', 'webhooks'] },
125130
{ key: 'security', label: 'Security', icon: Shield, types: ['roles', 'permissions', 'profiles', 'sharingRules', 'policies'] },
126-
{ key: 'ai', label: 'AI', icon: Bot, types: ['agents', 'ragPipelines'] },
131+
{ key: 'ai', label: 'AI', icon: Bot, types: ['agent', 'tool', 'ragPipeline'] },
127132
{ key: 'api', label: 'API', icon: Globe, types: ['apis', 'connectors'] },
128133
];
129134

apps/studio/src/plugins/built-in/ai-plugin.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,20 @@ export const aiProtocolPlugin: StudioPlugin = {
2323
key: 'ai',
2424
label: 'AI',
2525
icon: 'bot',
26-
metadataTypes: ['agents', 'ragPipelines'],
26+
metadataTypes: ['agent', 'tool', 'ragPipeline'],
2727
order: 50,
2828
},
2929
],
3030
metadataIcons: [
31-
{ metadataType: 'agents', label: 'Agents', icon: 'bot' },
32-
{ metadataType: 'ragPipelines', label: 'RAG Pipelines', icon: 'book-open' },
31+
{ metadataType: 'agent', label: 'Agents', icon: 'bot' },
32+
{ metadataType: 'tool', label: 'Tools', icon: 'wrench' },
33+
{ metadataType: 'ragPipeline', label: 'RAG Pipelines', icon: 'book-open' },
3334
],
3435
},
3536
}),
3637

3738
activate(api) {
38-
api.registerMetadataIcon('agents', Bot, 'Agents');
39-
api.registerMetadataIcon('ragPipelines', BookOpen, 'RAG Pipelines');
39+
api.registerMetadataIcon('agent', Bot, 'Agents');
40+
api.registerMetadataIcon('ragPipeline', BookOpen, 'RAG Pipelines');
4041
},
4142
};

apps/studio/src/plugins/built-in/default-plugin.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ const METADATA_TO_EXPORT_TYPE: Record<string, CodeExporterProps['type']> = {
3030
flows: 'flow',
3131
agent: 'agent',
3232
agents: 'agent',
33+
tool: 'tool',
34+
tools: 'tool',
3335
app: 'app',
3436
apps: 'app',
3537
};

packages/services/service-ai/src/plugin.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,22 @@ export class AIServicePlugin implements Plugin {
261261
registerDataTools(this.service.toolRegistry, { dataEngine });
262262
ctx.logger.info('[AI] Built-in data tools registered');
263263

264+
// Register data tools as metadata (for Studio visibility)
265+
if (metadataService) {
266+
const { DATA_TOOL_DEFINITIONS } = await import('./tools/data-tools.js');
267+
for (const toolDef of DATA_TOOL_DEFINITIONS) {
268+
const toolExists =
269+
typeof metadataService.exists === 'function'
270+
? await metadataService.exists('tool', toolDef.name)
271+
: false;
272+
273+
if (!toolExists) {
274+
await metadataService.register('tool', toolDef.name, toolDef);
275+
}
276+
}
277+
ctx.logger.info(`[AI] ${DATA_TOOL_DEFINITIONS.length} data tools registered as metadata`);
278+
}
279+
264280
// Register the built-in data_chat agent (requires metadata service)
265281
if (metadataService) {
266282
const agentExists =
@@ -286,6 +302,20 @@ export class AIServicePlugin implements Plugin {
286302
registerMetadataTools(this.service.toolRegistry, { metadataService });
287303
ctx.logger.info('[AI] Built-in metadata tools registered');
288304

305+
// Register metadata tools as metadata (for Studio visibility)
306+
const { METADATA_TOOL_DEFINITIONS } = await import('./tools/metadata-tools.js');
307+
for (const toolDef of METADATA_TOOL_DEFINITIONS) {
308+
const toolExists =
309+
typeof metadataService.exists === 'function'
310+
? await metadataService.exists('tool', toolDef.name)
311+
: false;
312+
313+
if (!toolExists) {
314+
await metadataService.register('tool', toolDef.name, toolDef);
315+
}
316+
}
317+
ctx.logger.info(`[AI] ${METADATA_TOOL_DEFINITIONS.length} metadata tools registered as metadata`);
318+
289319
// Register the built-in metadata_assistant agent
290320
const agentExists =
291321
typeof metadataService.exists === 'function'

0 commit comments

Comments
 (0)