Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
3. **Naming Convention:**
- **Configuration Keys (TS Props):** `camelCase` — e.g., `maxLength`, `referenceFilters`, `defaultValue`.
- **Machine Names (Data Values):** `snake_case` — e.g., `name: 'first_name'`, `object: 'project_task'`.
- **Metadata Type Names:** `singular` — e.g., `'agent'`, `'tool'`, `'view'`, `'flow'` (NOT `'agents'`, `'tools'`, `'views'`, `'flows'`). This aligns with the canonical `MetadataTypeSchema` enum in `packages/spec/src/kernel/metadata-plugin.zod.ts`.
- **REST API Endpoints:** `plural` — e.g., `/api/v1/ai/agents`, `/api/v1/ai/conversations` (per REST convention for resource collections).
4. **Namespace Imports:** Use `import { Data, UI, System } from '@objectstack/spec'` or subpath `import { Field } from '@objectstack/spec/data'`. Never use relative paths like `../../packages/spec`.
5. **Best Practice Mandate:**
- Benchmark against industry leaders (Salesforce, ServiceNow, Kubernetes) for structural decisions.
Expand Down
46 changes: 20 additions & 26 deletions apps/studio/src/components/app-sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,38 +73,32 @@ import {
// ─── Icon & label hints ──────────────────────────────────────────────
const META_TYPE_HINTS: Record<string, { label: string; icon: LucideIcon }> = {
object: { label: 'Objects', icon: Package },
objects: { label: 'Objects', icon: Package },
hooks: { label: 'Hooks', icon: Anchor },
mappings: { label: 'Mappings', icon: Map },
analyticsCubes: { label: 'Analytics Cubes', icon: PieChart },
hook: { label: 'Hooks', icon: Anchor },
mapping: { label: 'Mappings', icon: Map },
analyticsCube: { label: 'Analytics Cubes', icon: PieChart },
data: { label: 'Seed Data', icon: Database },
app: { label: 'Apps', icon: AppWindow },
apps: { label: 'Apps', icon: AppWindow },
actions: { label: 'Actions', icon: Zap },
views: { label: 'Views', icon: Eye },
pages: { label: 'Pages', icon: FileCode },
dashboards: { label: 'Dashboards', icon: BarChart3 },
reports: { label: 'Reports', icon: FileText },
themes: { label: 'Themes', icon: Palette },
flows: { label: 'Flows', icon: Workflow },
workflows: { label: 'Workflows', icon: Workflow },
approvals: { label: 'Approvals', icon: CheckSquare },
webhooks: { label: 'Webhooks', icon: Webhook },
roles: { label: 'Roles', icon: UserCog },
permissions: { label: 'Permissions', icon: Lock },
profiles: { label: 'Profiles', icon: Shield },
sharingRules: { label: 'Sharing Rules', icon: Shield },
policies: { label: 'Policies', icon: Shield },
action: { label: 'Actions', icon: Zap },
view: { label: 'Views', icon: Eye },
page: { label: 'Pages', icon: FileCode },
dashboard: { label: 'Dashboards', icon: BarChart3 },
report: { label: 'Reports', icon: FileText },
theme: { label: 'Themes', icon: Palette },
flow: { label: 'Flows', icon: Workflow },
workflow: { label: 'Workflows', icon: Workflow },
approval: { label: 'Approvals', icon: CheckSquare },
webhook: { label: 'Webhooks', icon: Webhook },
role: { label: 'Roles', icon: UserCog },
permission: { label: 'Permissions', icon: Lock },
profile: { label: 'Profiles', icon: Shield },
sharingRule: { label: 'Sharing Rules', icon: Shield },
policy: { label: 'Policies', icon: Shield },
agent: { label: 'Agents', icon: Bot },
agents: { label: 'Agents', icon: Bot },
tool: { label: 'Tools', icon: Wrench },
tools: { label: 'Tools', icon: Wrench },
ragPipeline: { label: 'RAG Pipelines', icon: BookOpen },
ragPipelines: { label: 'RAG Pipelines', icon: BookOpen },
apis: { label: 'APIs', icon: Globe },
connectors: { label: 'Connectors', icon: Link2 },
api: { label: 'APIs', icon: Globe },
connector: { label: 'Connectors', icon: Link2 },
plugin: { label: 'Plugins', icon: Layers },
plugins: { label: 'Plugins', icon: Layers },
kind: { label: 'Kinds', icon: Database },
};

Expand Down
10 changes: 5 additions & 5 deletions apps/studio/src/plugins/built-in/api-plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,19 @@ export const apiProtocolPlugin: StudioPlugin = {
key: 'api',
label: 'API',
icon: 'globe',
metadataTypes: ['apis', 'connectors'],
metadataTypes: ['api', 'connector'],
order: 60,
},
],
metadataIcons: [
{ metadataType: 'apis', label: 'APIs', icon: 'globe' },
{ metadataType: 'connectors', label: 'Connectors', icon: 'link-2' },
{ metadataType: 'api', label: 'APIs', icon: 'globe' },
{ metadataType: 'connector', label: 'Connectors', icon: 'link-2' },
],
},
}),

activate(api) {
api.registerMetadataIcon('apis', Globe, 'APIs');
api.registerMetadataIcon('connectors', Link2, 'Connectors');
api.registerMetadataIcon('api', Globe, 'APIs');
api.registerMetadataIcon('connector', Link2, 'Connectors');
},
};
18 changes: 9 additions & 9 deletions apps/studio/src/plugins/built-in/automation-plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,23 @@ export const automationProtocolPlugin: StudioPlugin = {
key: 'automation',
label: 'Automation',
icon: 'workflow',
metadataTypes: ['flows', 'workflows', 'approvals', 'webhooks'],
metadataTypes: ['flow', 'workflow', 'approval', 'webhook'],
order: 30,
},
],
metadataIcons: [
{ metadataType: 'flows', label: 'Flows', icon: 'workflow' },
{ metadataType: 'workflows', label: 'Workflows', icon: 'workflow' },
{ metadataType: 'approvals', label: 'Approvals', icon: 'check-square' },
{ metadataType: 'webhooks', label: 'Webhooks', icon: 'webhook' },
{ metadataType: 'flow', label: 'Flows', icon: 'workflow' },
{ metadataType: 'workflow', label: 'Workflows', icon: 'workflow' },
{ metadataType: 'approval', label: 'Approvals', icon: 'check-square' },
{ metadataType: 'webhook', label: 'Webhooks', icon: 'webhook' },
],
},
}),

activate(api) {
api.registerMetadataIcon('flows', Workflow, 'Flows');
api.registerMetadataIcon('workflows', Workflow, 'Workflows');
api.registerMetadataIcon('approvals', CheckSquare, 'Approvals');
api.registerMetadataIcon('webhooks', Webhook, 'Webhooks');
api.registerMetadataIcon('flow', Workflow, 'Flows');
api.registerMetadataIcon('workflow', Workflow, 'Workflows');
api.registerMetadataIcon('approval', CheckSquare, 'Approvals');
api.registerMetadataIcon('webhook', Webhook, 'Webhooks');
},
};
8 changes: 1 addition & 7 deletions apps/studio/src/plugins/built-in/default-plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,14 @@ import type { StudioPlugin, MetadataViewerProps } from '../types';

// ─── Helpers ─────────────────────────────────────────────────────────

/** Map Studio metadataType (often plural) to CodeExporter's ExportType (singular). */
/** Map Studio metadataType to CodeExporter's ExportType (all now use singular). */
const METADATA_TO_EXPORT_TYPE: Record<string, CodeExporterProps['type']> = {
object: 'object',
objects: 'object',
view: 'view',
views: 'view',
flow: 'flow',
flows: 'flow',
agent: 'agent',
agents: 'agent',
tool: 'tool',
tools: 'tool',
app: 'app',
apps: 'app',
};

// ─── Preview Viewer (JSON Inspector) ─────────────────────────────────
Expand Down
18 changes: 8 additions & 10 deletions apps/studio/src/plugins/built-in/object-plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const objectDesignerPlugin: StudioPlugin = {
metadataViewers: [
{
id: 'object-explorer',
metadataTypes: ['object', 'objects'],
metadataTypes: ['object'],
label: 'Object Explorer',
priority: 100,
modes: ['preview', 'data', 'code'],
Expand All @@ -43,16 +43,15 @@ export const objectDesignerPlugin: StudioPlugin = {
key: 'data',
label: 'Data',
icon: 'database',
metadataTypes: ['object', 'objects', 'hooks', 'mappings', 'analyticsCubes', 'data'],
metadataTypes: ['object', 'hook', 'mapping', 'analyticsCube', 'data'],
order: 10,
},
],
metadataIcons: [
{ metadataType: 'object', label: 'Objects', icon: 'package' },
{ metadataType: 'objects', label: 'Objects', icon: 'package' },
{ metadataType: 'hooks', label: 'Hooks', icon: 'anchor' },
{ metadataType: 'mappings', label: 'Mappings', icon: 'map' },
{ metadataType: 'analyticsCubes', label: 'Analytics Cubes', icon: 'pie-chart' },
{ metadataType: 'hook', label: 'Hooks', icon: 'anchor' },
{ metadataType: 'mapping', label: 'Mappings', icon: 'map' },
{ metadataType: 'analyticsCube', label: 'Analytics Cubes', icon: 'pie-chart' },
{ metadataType: 'data', label: 'Seed Data', icon: 'database' },
],
},
Expand All @@ -64,10 +63,9 @@ export const objectDesignerPlugin: StudioPlugin = {

// Register Lucide icons for metadata types
api.registerMetadataIcon('object', Package, 'Objects');
api.registerMetadataIcon('objects', Package, 'Objects');
api.registerMetadataIcon('hooks', Anchor, 'Hooks');
api.registerMetadataIcon('mappings', Map, 'Mappings');
api.registerMetadataIcon('analyticsCubes', PieChart, 'Analytics Cubes');
api.registerMetadataIcon('hook', Anchor, 'Hooks');
api.registerMetadataIcon('mapping', Map, 'Mappings');
api.registerMetadataIcon('analyticsCube', PieChart, 'Analytics Cubes');
api.registerMetadataIcon('data', Database, 'Seed Data');
},
};
22 changes: 11 additions & 11 deletions apps/studio/src/plugins/built-in/security-plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,25 @@ export const securityProtocolPlugin: StudioPlugin = {
key: 'security',
label: 'Security',
icon: 'shield',
metadataTypes: ['roles', 'permissions', 'profiles', 'sharingRules', 'policies'],
metadataTypes: ['role', 'permission', 'profile', 'sharingRule', 'policy'],
order: 40,
},
],
metadataIcons: [
{ metadataType: 'roles', label: 'Roles', icon: 'user-cog' },
{ metadataType: 'permissions', label: 'Permissions', icon: 'lock' },
{ metadataType: 'profiles', label: 'Profiles', icon: 'shield' },
{ metadataType: 'sharingRules', label: 'Sharing Rules', icon: 'shield' },
{ metadataType: 'policies', label: 'Policies', icon: 'shield' },
{ metadataType: 'role', label: 'Roles', icon: 'user-cog' },
{ metadataType: 'permission', label: 'Permissions', icon: 'lock' },
{ metadataType: 'profile', label: 'Profiles', icon: 'shield' },
{ metadataType: 'sharingRule', label: 'Sharing Rules', icon: 'shield' },
{ metadataType: 'policy', label: 'Policies', icon: 'shield' },
],
},
}),

activate(api) {
api.registerMetadataIcon('roles', UserCog, 'Roles');
api.registerMetadataIcon('permissions', Lock, 'Permissions');
api.registerMetadataIcon('profiles', Shield, 'Profiles');
api.registerMetadataIcon('sharingRules', Shield, 'Sharing Rules');
api.registerMetadataIcon('policies', Shield, 'Policies');
api.registerMetadataIcon('role', UserCog, 'Roles');
api.registerMetadataIcon('permission', Lock, 'Permissions');
api.registerMetadataIcon('profile', Shield, 'Profiles');
api.registerMetadataIcon('sharingRule', Shield, 'Sharing Rules');
api.registerMetadataIcon('policy', Shield, 'Policies');
},
};
26 changes: 13 additions & 13 deletions apps/studio/src/plugins/built-in/ui-plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,27 +25,27 @@ export const uiProtocolPlugin: StudioPlugin = {
key: 'ui',
label: 'UI',
icon: 'app-window',
metadataTypes: ['actions', 'views', 'pages', 'dashboards', 'reports', 'themes'],
metadataTypes: ['action', 'view', 'page', 'dashboard', 'report', 'theme'],
order: 20,
},
],
metadataIcons: [
{ metadataType: 'actions', label: 'Actions', icon: 'zap' },
{ metadataType: 'views', label: 'Views', icon: 'eye' },
{ metadataType: 'pages', label: 'Pages', icon: 'file-code' },
{ metadataType: 'dashboards', label: 'Dashboards', icon: 'bar-chart-3' },
{ metadataType: 'reports', label: 'Reports', icon: 'file-text' },
{ metadataType: 'themes', label: 'Themes', icon: 'palette' },
{ metadataType: 'action', label: 'Actions', icon: 'zap' },
{ metadataType: 'view', label: 'Views', icon: 'eye' },
{ metadataType: 'page', label: 'Pages', icon: 'file-code' },
{ metadataType: 'dashboard', label: 'Dashboards', icon: 'bar-chart-3' },
{ metadataType: 'report', label: 'Reports', icon: 'file-text' },
{ metadataType: 'theme', label: 'Themes', icon: 'palette' },
],
},
}),

activate(api) {
api.registerMetadataIcon('actions', Zap, 'Actions');
api.registerMetadataIcon('views', Eye, 'Views');
api.registerMetadataIcon('pages', FileCode, 'Pages');
api.registerMetadataIcon('dashboards', BarChart3, 'Dashboards');
api.registerMetadataIcon('reports', FileText, 'Reports');
api.registerMetadataIcon('themes', Palette, 'Themes');
api.registerMetadataIcon('action', Zap, 'Actions');
api.registerMetadataIcon('view', Eye, 'Views');
api.registerMetadataIcon('page', FileCode, 'Pages');
api.registerMetadataIcon('dashboard', BarChart3, 'Dashboards');
api.registerMetadataIcon('report', FileText, 'Reports');
api.registerMetadataIcon('theme', Palette, 'Themes');
},
};
14 changes: 14 additions & 0 deletions packages/spec/src/kernel/metadata-plugin.zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,20 @@ import { MergeStrategyConfigSchema, CustomizationPolicySchema } from './metadata
* The canonical list of all metadata types managed by the platform.
* Each type maps to a specific Zod schema (e.g., ObjectSchema, ViewSchema).
* Plugins can extend this registry via `contributes.kinds` in the manifest.
*
* ## Naming Convention
* **IMPORTANT:** All metadata type names are in **SINGULAR** form:
* - ✅ Use: `'agent'`, `'tool'`, `'skill'`, `'view'`, `'flow'`, `'action'`
* - ❌ NOT: `'agents'`, `'tools'`, `'skills'`, `'views'`, `'flows'`, `'actions'`
*
* This convention applies to:
* - Protocol definitions (this enum)
* - UI plugin registrations (`metadataTypes`, `metadataIcons`)
* - Metadata service operations
* - File patterns (`*.agent.ts`, `*.tool.ts`)
*
* REST API endpoints continue to use plural forms per REST conventions:
* - `/api/v1/ai/agents`, `/api/v1/ai/conversations`
*/
export const MetadataTypeSchema = z.enum([
// Data Protocol
Expand Down
Loading