spine-framework 0.3.125 → 0.3.126
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/.framework/cli/commands/agents.ts +35 -37
- package/.framework/cli/commands/auth.ts +35 -34
- package/.framework/cli/commands/create-app.ts +104 -40
- package/.framework/cli/commands/dev.ts +104 -69
- package/.framework/cli/commands/doctor.ts +169 -97
- package/.framework/cli/commands/generate.ts +82 -160
- package/.framework/cli/commands/init.ts +72 -34
- package/.framework/cli/commands/install-app.ts +260 -125
- package/.framework/cli/commands/items.ts +33 -44
- package/.framework/cli/commands/migrate.ts +122 -40
- package/.framework/cli/commands/migrations.ts +33 -40
- package/.framework/cli/commands/pipelines.ts +31 -39
- package/.framework/cli/commands/status.ts +47 -23
- package/.framework/cli/commands/system.ts +47 -37
- package/.framework/cli/commands/test.ts +112 -68
- package/.framework/cli/commands/validate-app.ts +215 -121
- package/.framework/cli/context.ts +112 -130
- package/.framework/cli/env-loader.ts +47 -18
- package/.framework/cli/index.ts +81 -42
- package/.framework/docs/runtime-types.md +1024 -0
- package/.framework/functions/_shared/agent-runner.ts +1296 -961
- package/.framework/functions/_shared/app-manifest.ts +82 -68
- package/.framework/functions/_shared/audit.ts +135 -83
- package/.framework/functions/_shared/{cil-state.ts → cil.ts} +147 -54
- package/.framework/functions/_shared/db.ts +80 -126
- package/.framework/functions/_shared/hash-api-key.ts +63 -0
- package/.framework/functions/_shared/index.ts +222 -347
- package/.framework/functions/_shared/kb.ts +319 -0
- package/.framework/functions/_shared/llm.ts +92 -0
- package/.framework/functions/_shared/logging.ts +288 -0
- package/.framework/functions/_shared/middleware.ts +329 -365
- package/.framework/functions/_shared/outcomes.ts +36 -0
- package/.framework/functions/_shared/permissions.ts +359 -643
- package/.framework/functions/_shared/pipeline-runner.ts +243 -316
- package/.framework/functions/_shared/principal.ts +376 -468
- package/.framework/functions/_shared/resolve-credentials.ts +102 -0
- package/.framework/functions/_shared/resolve-ids.ts +162 -14
- package/.framework/functions/_shared/retry-deliveries.ts +104 -0
- package/.framework/functions/_shared/schema-utils.ts +611 -373
- package/.framework/functions/_shared/testing.ts +207 -137
- package/.framework/functions/_shared/tracing.ts +276 -0
- package/.framework/functions/_shared/trigger-engine.ts +159 -211
- package/.framework/functions/_shared/webhook-registration.ts +95 -81
- package/.framework/functions/_shared/webhook-registry.ts +153 -75
- package/.framework/functions/account-nodes.ts +31 -53
- package/.framework/functions/adapters/generic-webhook-inbound.ts +56 -0
- package/.framework/functions/adapters/generic-webhook-outbound.ts +43 -0
- package/.framework/functions/adapters/openai-outbound.ts +40 -0
- package/.framework/functions/admin-data.ts +687 -533
- package/.framework/functions/admin-funnel.ts +31 -20
- package/.framework/functions/admin-install-funnel.ts +47 -28
- package/.framework/functions/admin-signals.ts +47 -29
- package/.framework/functions/ai-agents.ts +122 -147
- package/.framework/functions/ai-interactions.ts +180 -90
- package/.framework/functions/api-keys.ts +250 -192
- package/.framework/functions/apps.ts +203 -197
- package/.framework/functions/auth.ts +98 -91
- package/.framework/functions/cil-agent-ingest.ts +773 -0
- package/.framework/functions/cil-agent.ts +592 -0
- package/.framework/functions/cil-callmap.ts +1227 -0
- package/.framework/functions/cil-config.ts +583 -0
- package/.framework/functions/cil-context.ts +445 -0
- package/.framework/functions/cil-doc.ts +1752 -0
- package/.framework/functions/cil-embeddings.ts +1202 -0
- package/.framework/functions/cil-graph.ts +585 -0
- package/.framework/functions/cil-ingest.ts +2416 -0
- package/.framework/functions/cil-pipeline.ts +318 -0
- package/.framework/functions/cil-project.ts +499 -0
- package/.framework/functions/cil-validate.ts +469 -0
- package/.framework/functions/debug-auth.ts +73 -53
- package/.framework/functions/deliveries.ts +117 -0
- package/.framework/functions/embeddings.ts +528 -516
- package/.framework/functions/eval-harness.ts +158 -106
- package/.framework/functions/integration-outbound.ts +311 -0
- package/.framework/functions/integration-routes.ts +240 -466
- package/.framework/functions/integrations.ts +132 -140
- package/.framework/functions/invites.ts +401 -201
- package/.framework/functions/item-progress.ts +113 -53
- package/.framework/functions/kb.ts +28 -0
- package/.framework/functions/logs.ts +239 -222
- package/.framework/functions/observability.ts +308 -259
- package/.framework/functions/pipeline-executions.ts +179 -235
- package/.framework/functions/pipelines.ts +163 -205
- package/.framework/functions/prompt-configs.ts +109 -156
- package/.framework/functions/roles.ts +97 -147
- package/.framework/functions/system-cron.ts +132 -218
- package/.framework/functions/system.ts +112 -52
- package/.framework/functions/tests.ts +32 -28
- package/.framework/functions/timers.ts +162 -210
- package/.framework/functions/triggers.ts +282 -346
- package/.framework/functions/types.ts +283 -400
- package/.framework/migrations/001_core_schema.sql +630 -0
- package/.framework/migrations/002_core_rls_and_functions.sql +532 -0
- package/.framework/migrations/{003_system_data.sql → 003_core_system_data.sql} +26 -153
- package/.framework/migrations/004_core_rpc_and_broker.sql +421 -0
- package/.framework/migrations/005_core_observability.sql +598 -0
- package/.framework/migrations/006_security_hardening_rls.sql +97 -0
- package/.framework/migrations/007_kb_article_list.sql +237 -0
- package/.framework/migrations/008_items_target.sql +8 -0
- package/.framework/migrations/009_roles_slug_unique.sql +11 -0
- package/.framework/public/spine.config.json +91 -0
- package/.framework/scripts/app-install-cli.ts +112 -98
- package/.framework/src/App.tsx +67 -20
- package/.framework/src/apps/admin/index.tsx +97 -27
- package/.framework/src/components/AppWrapper.tsx +50 -11
- package/.framework/src/components/CustomAppLoader.tsx +131 -22
- package/.framework/src/components/admin/AdminListPage.tsx +75 -8
- package/.framework/src/components/admin/AdminSidebar.tsx +148 -36
- package/.framework/src/components/admin/AdminStatsCard.tsx +48 -29
- package/.framework/src/components/admin/PageInstructions.tsx +49 -0
- package/.framework/src/components/admin/SortableTableHeader.tsx +49 -2
- package/.framework/src/components/app-shell/GenericAppShell.tsx +69 -11
- package/.framework/src/components/app-shell/GenericDetailPage.tsx +55 -10
- package/.framework/src/components/app-shell/GenericListPage.tsx +76 -9
- package/.framework/src/components/app-sidebar.tsx +50 -3
- package/.framework/src/components/auth/ProtectedRoute.tsx +53 -45
- package/.framework/src/components/kb/KBArticleEditor.tsx +409 -0
- package/.framework/src/components/kb/KBArticleList.tsx +557 -0
- package/.framework/src/components/layout/AppShell.tsx +54 -16
- package/.framework/src/components/layout/Header.tsx +50 -38
- package/.framework/src/components/layout/Layout.tsx +48 -32
- package/.framework/src/components/layout/Sidebar.tsx +167 -16
- package/.framework/src/components/runtime/DataDetailHeader.tsx +33 -1
- package/.framework/src/components/runtime/DataDetailPage.tsx +289 -4
- package/.framework/src/components/runtime/DataFilters.tsx +78 -1
- package/.framework/src/components/runtime/DataHeader.tsx +32 -29
- package/.framework/src/components/runtime/DataListPage.tsx +161 -2
- package/.framework/src/components/runtime/DataStats.tsx +48 -1
- package/.framework/src/components/runtime/DataTable.tsx +153 -1
- package/.framework/src/components/runtime/SchemaDetailForm.tsx +77 -46
- package/.framework/src/components/runtime/index.ts +16 -9
- package/.framework/src/components/search-form.tsx +33 -1
- package/.framework/src/components/shared/AgentView.tsx +48 -51
- package/.framework/src/components/shared/FieldRenderer.tsx +84 -67
- package/.framework/src/components/shared/InviteManager.tsx +113 -52
- package/.framework/src/components/shared/MemberList.tsx +182 -0
- package/.framework/src/components/shared/SchemaFields.tsx +96 -78
- package/.framework/src/components/ui/DataTable.tsx +86 -56
- package/.framework/src/components/ui/Form.tsx +188 -109
- package/.framework/src/components/ui/ItemCard.tsx +86 -58
- package/.framework/src/components/ui/ItemListView.tsx +88 -61
- package/.framework/src/components/ui/LoadingSpinner.tsx +52 -27
- package/.framework/src/components/ui/Modal.tsx +81 -4
- package/.framework/src/components/ui/RichTextEditor.tsx +101 -9
- package/.framework/src/components/ui/accordion.tsx +97 -5
- package/.framework/src/components/ui/alert-dialog.tsx +225 -13
- package/.framework/src/components/ui/alert.tsx +113 -6
- package/.framework/src/components/ui/aspect-ratio.tsx +49 -2
- package/.framework/src/components/ui/avatar.tsx +129 -7
- package/.framework/src/components/ui/badge.tsx +65 -3
- package/.framework/src/components/ui/breadcrumb.tsx +145 -8
- package/.framework/src/components/ui/button-group.tsx +81 -4
- package/.framework/src/components/ui/button.tsx +49 -2
- package/.framework/src/components/ui/calendar.tsx +65 -3
- package/.framework/src/components/ui/card.tsx +145 -8
- package/.framework/src/components/ui/carousel.tsx +129 -7
- package/.framework/src/components/ui/chart.tsx +161 -10
- package/.framework/src/components/ui/checkbox.tsx +49 -2
- package/.framework/src/components/ui/collapsible.tsx +81 -5
- package/.framework/src/components/ui/combobox.tsx +305 -20
- package/.framework/src/components/ui/command.tsx +177 -11
- package/.framework/src/components/ui/context-menu.tsx +273 -17
- package/.framework/src/components/ui/dialog.tsx +209 -27
- package/.framework/src/components/ui/direction.tsx +64 -4
- package/.framework/src/components/ui/drawer.tsx +193 -12
- package/.framework/src/components/ui/dropdown-menu.tsx +273 -18
- package/.framework/src/components/ui/empty.tsx +145 -9
- package/.framework/src/components/ui/field.tsx +209 -14
- package/.framework/src/components/ui/hover-card.tsx +81 -4
- package/.framework/src/components/ui/input-group.tsx +162 -10
- package/.framework/src/components/ui/input-otp.tsx +98 -5
- package/.framework/src/components/ui/input.tsx +49 -2
- package/.framework/src/components/ui/item.tsx +225 -13
- package/.framework/src/components/ui/kbd.tsx +65 -3
- package/.framework/src/components/ui/label.tsx +49 -2
- package/.framework/src/components/ui/menubar.tsx +289 -17
- package/.framework/src/components/ui/native-select.tsx +97 -5
- package/.framework/src/components/ui/navigation-menu.tsx +177 -10
- package/.framework/src/components/ui/pagination.tsx +161 -9
- package/.framework/src/components/ui/popover.tsx +145 -8
- package/.framework/src/components/ui/progress.tsx +49 -2
- package/.framework/src/components/ui/radio-group.tsx +65 -3
- package/.framework/src/components/ui/resizable.tsx +82 -4
- package/.framework/src/components/ui/scroll-area.tsx +65 -3
- package/.framework/src/components/ui/select.tsx +193 -11
- package/.framework/src/components/ui/separator.tsx +49 -2
- package/.framework/src/components/ui/sheet.tsx +193 -11
- package/.framework/src/components/ui/sidebar.tsx +481 -38
- package/.framework/src/components/ui/skeleton.tsx +49 -2
- package/.framework/src/components/ui/slider.tsx +49 -2
- package/.framework/src/components/ui/sonner.tsx +49 -2
- package/.framework/src/components/ui/spinner.tsx +49 -2
- package/.framework/src/components/ui/switch.tsx +49 -2
- package/.framework/src/components/ui/table-primitives.tsx +160 -33
- package/.framework/src/components/ui/table.tsx +161 -9
- package/.framework/src/components/ui/tabs.tsx +113 -6
- package/.framework/src/components/ui/textarea.tsx +49 -2
- package/.framework/src/components/ui/toggle-group.tsx +81 -4
- package/.framework/src/components/ui/toggle.tsx +65 -3
- package/.framework/src/components/ui/tooltip.tsx +97 -5
- package/.framework/src/contexts/AppContext.tsx +129 -45
- package/.framework/src/contexts/AuthContext.tsx +173 -145
- package/.framework/src/hooks/use-mobile.ts +48 -2
- package/.framework/src/hooks/useApi.ts +208 -159
- package/.framework/src/hooks/useAppPath.ts +32 -23
- package/.framework/src/hooks/useApps.ts +51 -20
- package/.framework/src/hooks/useEntityList.ts +32 -78
- package/.framework/src/hooks/useEntityRecord.ts +35 -96
- package/.framework/src/hooks/useForm.ts +32 -92
- package/.framework/src/hooks/useListSchema.ts +49 -78
- package/.framework/src/hooks/useSchemaRecord.ts +114 -105
- package/.framework/src/lib/api.ts +192 -115
- package/.framework/src/lib/supabase.ts +98 -64
- package/.framework/src/lib/utils.ts +287 -151
- package/.framework/src/main.tsx +49 -3
- package/.framework/src/pages/DashboardPage.tsx +52 -29
- package/.framework/src/pages/NotFoundPage.tsx +32 -10
- package/.framework/src/pages/SetupPage.tsx +32 -12
- package/.framework/src/pages/admin/AIAgentDetailPage.tsx +119 -10
- package/.framework/src/pages/admin/AIAgentsPage.tsx +48 -19
- package/.framework/src/pages/admin/APIKeyDetailPage.tsx +187 -17
- package/.framework/src/pages/admin/APIKeysPage.tsx +98 -22
- package/.framework/src/pages/admin/AlertsConfigPage.tsx +113 -26
- package/.framework/src/pages/admin/AppDetailPage.tsx +125 -8
- package/.framework/src/pages/admin/AppsPage.tsx +49 -2
- package/.framework/src/pages/admin/DeliveriesPage.tsx +196 -0
- package/.framework/src/pages/admin/DesignedPage.tsx +32 -18
- package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +215 -484
- package/.framework/src/pages/admin/EmbeddingsPage.tsx +116 -319
- package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +34 -9
- package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +34 -9
- package/.framework/src/pages/admin/IntegratedDashboard.tsx +32 -16
- package/.framework/src/pages/admin/IntegrationDetailPage.tsx +183 -26
- package/.framework/src/pages/admin/IntegrationsPage.tsx +48 -19
- package/.framework/src/pages/admin/InvitesPage.tsx +48 -14
- package/.framework/src/pages/admin/LogsPage.tsx +422 -75
- package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +34 -9
- package/.framework/src/pages/admin/ObservabilityDashboard.tsx +113 -24
- package/.framework/src/pages/admin/PipelineDetailPage.tsx +206 -34
- package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +50 -17
- package/.framework/src/pages/admin/PipelinesPage.tsx +160 -21
- package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +378 -88
- package/.framework/src/pages/admin/PromptConfigsPage.tsx +125 -16
- package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +49 -10
- package/.framework/src/pages/admin/RoleDetailPage.tsx +130 -10
- package/.framework/src/pages/admin/RolesPage.tsx +171 -18
- package/.framework/src/pages/admin/SelectTestPage.tsx +34 -9
- package/.framework/src/pages/admin/ShadcnTestPage.tsx +49 -11
- package/.framework/src/pages/admin/SimpleDashboard.tsx +49 -10
- package/.framework/src/pages/admin/TestRunDetailPage.tsx +49 -4
- package/.framework/src/pages/admin/TestingDashboard.tsx +98 -28
- package/.framework/src/pages/admin/TimerDetailPage.tsx +143 -33
- package/.framework/src/pages/admin/TimersPage.tsx +48 -20
- package/.framework/src/pages/admin/TriggerDetailPage.tsx +118 -30
- package/.framework/src/pages/admin/TriggersPage.tsx +64 -19
- package/.framework/src/pages/admin/TypeDetailPage.tsx +138 -15
- package/.framework/src/pages/admin/TypesPage.tsx +48 -20
- package/.framework/src/pages/admin/cil/CILAgentPage.tsx +465 -0
- package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +787 -0
- package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +699 -0
- package/.framework/src/pages/admin/cil/CILFileListPage.tsx +647 -0
- package/.framework/src/pages/admin/cil/CILGraphPage.tsx +616 -0
- package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +1402 -0
- package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +614 -0
- package/.framework/src/pages/admin/cil/CILSearchPage.tsx +571 -0
- package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +731 -0
- package/.framework/src/pages/admin/kb/KBAdminPage.tsx +64 -0
- package/.framework/src/pages/auth/AuthConfirmPage.tsx +52 -51
- package/.framework/src/pages/auth/ForgotPasswordPage.tsx +31 -22
- package/.framework/src/pages/auth/LoginPage.tsx +50 -23
- package/.framework/src/pages/auth/PendingApprovalPage.tsx +31 -15
- package/.framework/src/pages/auth/RegisterPage.tsx +281 -317
- package/.framework/src/pages/spine-framework/APIPage.tsx +33 -0
- package/.framework/src/pages/spine-framework/CLIPage.tsx +33 -0
- package/.framework/src/types/auth.ts +128 -71
- package/.framework/src/types/types.ts +373 -157
- package/custom/.devin/skills/spine-workbench-discovery/SKILL.md +39 -0
- package/custom/.devin/skills/spine-workbench-idea/SKILL.md +36 -0
- package/custom/.devin/skills/spine-workbench-implement/SKILL.md +46 -0
- package/custom/.devin/skills/spine-workbench-initiative/SKILL.md +28 -0
- package/custom/.devin/skills/spine-workbench-plan/SKILL.md +38 -0
- package/docs/README.md +9 -130
- package/netlify.toml +3 -3
- package/package.json +13 -25
- package/scripts/kb-ingest-docs.ts +203 -0
- package/spine.config.json +65 -4
- package/.framework/migrations/001_schema.sql +0 -425
- package/.framework/migrations/002_rls_and_functions.sql +0 -763
- package/.framework/migrations/004_enhancements.sql +0 -43
- package/.framework/migrations/005_auth_user_trigger.sql +0 -105
- package/.framework/migrations/006_fix_current_actor_id.sql +0 -21
- package/.framework/migrations/016_invites.sql +0 -27
- package/.framework/migrations/017_fix_get_account_apps.sql +0 -78
- package/.framework/migrations/018_apps_required_roles.sql +0 -17
- package/.framework/migrations/019_triggers_unique_constraint.sql +0 -13
- package/.framework/migrations/020_get_account_apps_role_filter.sql +0 -117
- package/.framework/migrations/021_app_domains.sql +0 -112
- package/.framework/migrations/022_route_prefix_domain_unique.sql +0 -21
- package/.framework/migrations/023_match_embeddings_rpc.sql +0 -78
- package/.framework/migrations/024_messages_account_id.sql +0 -9
- package/.framework/migrations/025_retype_threads_messages.sql +0 -240
- package/.framework/migrations/026_fix_rls_policies.sql +0 -47
- package/.framework/migrations/027_embedding_lifecycle.sql +0 -176
- package/.framework/migrations/028_fix_message_data_permissions.sql +0 -49
- package/.framework/migrations/029_tighten_support_triage_prompt.sql +0 -41
- package/.framework/migrations/030_messages_updated_by.sql +0 -6
- package/.framework/migrations/031_seed_upsert_constraints.sql +0 -35
- package/docs/APPS.md +0 -232
- package/docs/ARCHITECTURE.md +0 -246
- package/docs/INSTALL.md +0 -155
- package/docs/design-schema-spec.md +0 -1837
- package/docs/dev-guides/01-create-an-app.md +0 -183
- package/docs/dev-guides/02-create-a-function.md +0 -178
- package/docs/dev-guides/03-create-a-component.md +0 -178
- package/docs/dev-guides/04-webhook-handlers.md +0 -129
- package/docs/dev-guides/05-testing.md +0 -168
- package/docs/dev-guides/README.md +0 -40
- package/docs/npm-packages-plan.md +0 -288
- package/docs/spine-core--api-reference.md +0 -822
|
@@ -0,0 +1,616 @@
|
|
|
1
|
+
// CIL[BEGIN chunk_id="cilgraphpage_module_header_1784193942" type="module_header" identity="module_header" parent="none"]
|
|
2
|
+
// CIL[DOC-MACRO purpose="Imports and dependencies for the CIL graph visualization page"]
|
|
3
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Declare external libraries, hooks, UI components, and icons used by CILGraphPage"]
|
|
4
|
+
// CIL[DOC-CONTEXT module="cortex:cil-graph" layer="presentation" related_files="[\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"custom/apps/portal/pages/ContentPage.tsx\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\".framework/src/pages/admin/RolesPage.tsx\",\"\\\"]"]
|
|
5
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="imported modules and types" errors="none" side_effects="none"]
|
|
6
|
+
// CIL[DOC-MICRO logic_summary="Aggregates React, react-router, XYFlow, dagre, internal api/hooks, UI primitives, and lucide icons." notable_decisions="[]"]
|
|
7
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
8
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
9
|
+
// CIL[DOC-AUDIENCE audience="developer"]
|
|
10
|
+
// CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: custom/apps/cortex/pages/operations/OperationsDashboard.tsx, custom/apps/portal/pages/ContentPage.tsx, .framework/src/pages/admin/TypeDetailPage.tsx, .framework/src/pages/admin/RolesPage.tsx, \."]
|
|
11
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
12
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
13
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
14
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
15
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
16
|
+
import { useEffect, useState, useCallback } from 'react'
|
|
17
|
+
import { useParams } from 'react-router-dom'
|
|
18
|
+
import {
|
|
19
|
+
ReactFlow,
|
|
20
|
+
Background,
|
|
21
|
+
Controls,
|
|
22
|
+
MiniMap,
|
|
23
|
+
useNodesState,
|
|
24
|
+
useEdgesState,
|
|
25
|
+
addEdge,
|
|
26
|
+
type Node,
|
|
27
|
+
type Edge,
|
|
28
|
+
type Connection,
|
|
29
|
+
MarkerType,
|
|
30
|
+
Panel,
|
|
31
|
+
} from '@xyflow/react'
|
|
32
|
+
import '@xyflow/react/dist/style.css'
|
|
33
|
+
import dagre from 'dagre'
|
|
34
|
+
import { apiFetch } from '@core/lib/api'
|
|
35
|
+
import { Button } from '@core/components/ui/button'
|
|
36
|
+
import { Badge } from '@core/components/ui/badge'
|
|
37
|
+
import { Skeleton } from '@core/components/ui/skeleton'
|
|
38
|
+
import {
|
|
39
|
+
Select,
|
|
40
|
+
SelectContent,
|
|
41
|
+
SelectItem,
|
|
42
|
+
SelectTrigger,
|
|
43
|
+
SelectValue,
|
|
44
|
+
} from '@core/components/ui/select'
|
|
45
|
+
import { RefreshCw, ChevronRight, ZoomIn, Layers } from 'lucide-react'
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
import { PageInstructions } from '../../../components/admin/PageInstructions'
|
|
50
|
+
// CIL[END chunk_id="cilgraphpage_module_header_1784193942"]
|
|
51
|
+
// CIL[BEGIN chunk_id="cilgraphpage_node_width_1784193942" type="constant" identity="NODE_WIDTH" parent="none"]
|
|
52
|
+
// CIL[DOC-MACRO purpose="Define default width for chunk graph nodes"]
|
|
53
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Provide constant node width used in layout and rendering"]
|
|
54
|
+
// CIL[DOC-CONTEXT module="cortex:cil-graph" layer="presentation" related_files="[\".framework/functions/_shared/principal.ts\",\".framework/functions/_shared/schema-utils.ts\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"\\\"]"]
|
|
55
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="NODE_WIDTH number" errors="none" side_effects="none"]
|
|
56
|
+
// CIL[DOC-MICRO logic_summary="Declares a fixed width of 180 pixels for chunk nodes." notable_decisions="[]"]
|
|
57
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
58
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
59
|
+
// CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: .framework/functions/_shared/principal.ts, .framework/functions/_shared/schema-utils.ts, .framework/src/pages/admin/IntegrationsPage.tsx, .framework/src/pages/admin/TypeDetailPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, \."]
|
|
60
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
61
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
62
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
63
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
64
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
65
|
+
const NODE_WIDTH = 180
|
|
66
|
+
// CIL[END chunk_id="cilgraphpage_node_width_1784193942"]
|
|
67
|
+
// CIL[BEGIN chunk_id="cilgraphpage_node_height_1784193942" type="constant" identity="NODE_HEIGHT" parent="none"]
|
|
68
|
+
// CIL[DOC-MACRO purpose="Define default height for chunk graph nodes"]
|
|
69
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Provide constant node height used in layout and rendering"]
|
|
70
|
+
// CIL[DOC-CONTEXT module="cortex:cil-graph" layer="presentation" related_files="[\".framework/functions/_shared/principal.ts\",\".framework/functions/_shared/schema-utils.ts\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"\\\"]"]
|
|
71
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="NODE_HEIGHT number" errors="none" side_effects="none"]
|
|
72
|
+
// CIL[DOC-MICRO logic_summary="Declares a fixed height of 60 pixels for chunk nodes." notable_decisions="[]"]
|
|
73
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
74
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
75
|
+
// CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: .framework/functions/_shared/principal.ts, .framework/functions/_shared/schema-utils.ts, .framework/src/pages/admin/IntegrationsPage.tsx, .framework/src/pages/admin/TypeDetailPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, \."]
|
|
76
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
77
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
78
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
79
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
80
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
81
|
+
const NODE_HEIGHT = 60
|
|
82
|
+
// CIL[END chunk_id="cilgraphpage_node_height_1784193942"]
|
|
83
|
+
// CIL[BEGIN chunk_id="cilgraphpage_file_width_1784193942" type="constant" identity="FILE_WIDTH" parent="none"]
|
|
84
|
+
// CIL[DOC-MACRO purpose="Define default width for file graph nodes"]
|
|
85
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Provide constant file node width used in layout and rendering"]
|
|
86
|
+
// CIL[DOC-CONTEXT module="cortex:cil-graph" layer="presentation" related_files="[\".framework/functions/_shared/principal.ts\",\".framework/functions/_shared/schema-utils.ts\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"\\\"]"]
|
|
87
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="FILE_WIDTH number" errors="none" side_effects="none"]
|
|
88
|
+
// CIL[DOC-MICRO logic_summary="Declares a fixed width of 200 pixels for file nodes." notable_decisions="[]"]
|
|
89
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
90
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
91
|
+
// CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: .framework/functions/_shared/principal.ts, .framework/functions/_shared/schema-utils.ts, .framework/src/pages/admin/IntegrationsPage.tsx, .framework/src/pages/admin/TypeDetailPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, \."]
|
|
92
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
93
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
94
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
95
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
96
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
97
|
+
const FILE_WIDTH = 200
|
|
98
|
+
// CIL[END chunk_id="cilgraphpage_file_width_1784193942"]
|
|
99
|
+
// CIL[BEGIN chunk_id="cilgraphpage_file_height_1784193942" type="constant" identity="FILE_HEIGHT" parent="none"]
|
|
100
|
+
// CIL[DOC-MACRO purpose="Define default height for file graph nodes"]
|
|
101
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Provide constant file node height used in layout and rendering"]
|
|
102
|
+
// CIL[DOC-CONTEXT module="cortex:cil-graph" layer="presentation" related_files="[\".framework/functions/_shared/principal.ts\",\".framework/functions/_shared/schema-utils.ts\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"\\\"]"]
|
|
103
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="FILE_HEIGHT number" errors="none" side_effects="none"]
|
|
104
|
+
// CIL[DOC-MICRO logic_summary="Declares a fixed height of 40 pixels for file nodes." notable_decisions="[]"]
|
|
105
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
106
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
107
|
+
// CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: .framework/functions/_shared/principal.ts, .framework/functions/_shared/schema-utils.ts, .framework/src/pages/admin/IntegrationsPage.tsx, .framework/src/pages/admin/TypeDetailPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, \."]
|
|
108
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
109
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
110
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
111
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
112
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
113
|
+
const FILE_HEIGHT = 40
|
|
114
|
+
|
|
115
|
+
// CIL[END chunk_id="cilgraphpage_file_height_1784193942"]
|
|
116
|
+
// CIL[BEGIN chunk_id="cilgraphpage_viewmode_1784193942" type="type" identity="ViewMode" parent="none"]
|
|
117
|
+
// CIL[DOC-MACRO purpose="Enumerate valid graph view modes"]
|
|
118
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Type alias restricting view mode values"]
|
|
119
|
+
// CIL[DOC-CONTEXT module="cortex:cil-graph" layer="presentation" related_files="[]"]
|
|
120
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="ViewMode union type" errors="none" side_effects="none"]
|
|
121
|
+
// CIL[DOC-MICRO logic_summary="Defines allowed view modes for the graph: files, chunks, or mixed." notable_decisions="[]"]
|
|
122
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
123
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
124
|
+
// CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
125
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
126
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
127
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
128
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
129
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
130
|
+
type ViewMode = 'files' | 'chunks' | 'mixed'
|
|
131
|
+
|
|
132
|
+
// CIL[END chunk_id="cilgraphpage_viewmode_1784193942"]
|
|
133
|
+
// CIL[BEGIN chunk_id="cilgraphpage_layoutgraph_1784193942" type="function" identity="layoutGraph" parent="none"]
|
|
134
|
+
// CIL[DOC-MACRO purpose="Compute directed graph layout for React Flow nodes and edges"]
|
|
135
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Arrange nodes using Dagre left-to-right layout and return positioned elements"]
|
|
136
|
+
// CIL[DOC-CONTEXT module="cortex:cil-graph" layer="presentation" related_files="[]"]
|
|
137
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="{nodes: Node[]; edges: Edge[]}" errors="none" side_effects="none"]
|
|
138
|
+
// CIL[DOC-MICRO logic_summary="Builds a dagre graph, sets LR options, adds nodes/edges with dynamic widths/heights, runs layout, then centers each node by subtracting half its size." notable_decisions="['Uses file dimensions for file nodes and chunk dimensions otherwise','Centers node positions by subtracting half width/height']"]
|
|
139
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
140
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
141
|
+
// CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
142
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
143
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
144
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
145
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
146
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
147
|
+
function layoutGraph(nodes: Node[], edges: Edge[]): { nodes: Node[]; edges: Edge[] } {
|
|
148
|
+
const g = new dagre.graphlib.Graph()
|
|
149
|
+
g.setDefaultEdgeLabel(() => ({}))
|
|
150
|
+
g.setGraph({ rankdir: 'LR', nodesep: 40, ranksep: 80 })
|
|
151
|
+
|
|
152
|
+
for (const node of nodes) {
|
|
153
|
+
g.setNode(node.id, { width: node.data?.isFile ? FILE_WIDTH : NODE_WIDTH, height: node.data?.isFile ? FILE_HEIGHT : NODE_HEIGHT })
|
|
154
|
+
}
|
|
155
|
+
for (const edge of edges) {
|
|
156
|
+
g.setEdge(edge.source, edge.target)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
dagre.layout(g)
|
|
160
|
+
|
|
161
|
+
const positionedNodes = nodes.map(node => {
|
|
162
|
+
const pos = g.node(node.id)
|
|
163
|
+
const w = node.data?.isFile ? FILE_WIDTH : NODE_WIDTH
|
|
164
|
+
const h = node.data?.isFile ? FILE_HEIGHT : NODE_HEIGHT
|
|
165
|
+
return { ...node, position: { x: pos.x - w / 2, y: pos.y - h / 2 } }
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
return { nodes: positionedNodes, edges }
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
// CIL[END chunk_id="cilgraphpage_layoutgraph_1784193942"]
|
|
174
|
+
// CIL[BEGIN chunk_id="cilgraphpage_chunk_type_colors_1784193942" type="constant" identity="CHUNK_TYPE_COLORS" parent="none"]
|
|
175
|
+
// CIL[DOC-MACRO purpose="Map chunk types to display colors"]
|
|
176
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Provide color palette for graph legend and node styling"]
|
|
177
|
+
// CIL[DOC-CONTEXT module="cortex:cil-graph" layer="presentation" related_files="[]"]
|
|
178
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="Record<string,string> color map" errors="none" side_effects="none"]
|
|
179
|
+
// CIL[DOC-MICRO logic_summary="Color lookup table mapping chunk type strings to hex colors for nodes and legend." notable_decisions="[]"]
|
|
180
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
181
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
182
|
+
// CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
183
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
184
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
185
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
186
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
187
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
188
|
+
const CHUNK_TYPE_COLORS: Record<string, string> = {
|
|
189
|
+
function: '#6366F1',
|
|
190
|
+
class: '#8B5CF6',
|
|
191
|
+
interface: '#10B981',
|
|
192
|
+
type: '#06B6D4',
|
|
193
|
+
component: '#F59E0B',
|
|
194
|
+
hook: '#EC4899',
|
|
195
|
+
route: '#EF4444',
|
|
196
|
+
config: '#64748B',
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// CIL[END chunk_id="cilgraphpage_chunk_type_colors_1784193942"]
|
|
200
|
+
// CIL[BEGIN chunk_id="cilgraphpage_nodecolor_1784193942" type="function" identity="nodeColor" parent="none"]
|
|
201
|
+
// CIL[DOC-MACRO purpose="Resolve a display color for a graph node"]
|
|
202
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Return the appropriate color based on file, dead-code, or chunk type"]
|
|
203
|
+
// CIL[DOC-CONTEXT module="cortex:cil-graph" layer="presentation" related_files="[]"]
|
|
204
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="hex color string" errors="none" side_effects="none"]
|
|
205
|
+
// CIL[DOC-MICRO logic_summary="Returns slate for file nodes, gray for dead code, or CHUNK_TYPE_COLORS lookup with an indigo fallback." notable_decisions="['Falls back to indigo when chunk type has no mapped color']"]
|
|
206
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
207
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
208
|
+
// CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
209
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
210
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
211
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
212
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
213
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
214
|
+
function nodeColor(node: Node): string {
|
|
215
|
+
if (node.data?.isFile) return '#1E293B'
|
|
216
|
+
if (node.data?.is_dead_code) return '#94A3B8'
|
|
217
|
+
return CHUNK_TYPE_COLORS[node.data?.chunk_type as string] || '#6366F1'
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
// CIL[END chunk_id="cilgraphpage_nodecolor_1784193942"]
|
|
223
|
+
// CIL[BEGIN chunk_id="cilgraphpage_projectgraph_1784193942" type="interface" identity="ProjectGraph" parent="none"]
|
|
224
|
+
// CIL[DOC-MACRO purpose="Describe the shape of the project graph API response"]
|
|
225
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Define the TypeScript contract for nodes and edges data"]
|
|
226
|
+
// CIL[DOC-CONTEXT module="cortex:cil-graph" layer="presentation" related_files="[]"]
|
|
227
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="ProjectGraph interface" errors="none" side_effects="none"]
|
|
228
|
+
// CIL[DOC-MICRO logic_summary="Declares nodes containing files and chunks arrays and edges containing imports and calls arrays, using any for metadata extensibility." notable_decisions="['Uses any types for flexible API schema']"]
|
|
229
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
230
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
231
|
+
// CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
232
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
233
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
234
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
235
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
236
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
237
|
+
interface ProjectGraph {
|
|
238
|
+
nodes: {
|
|
239
|
+
files: any[]
|
|
240
|
+
chunks: any[]
|
|
241
|
+
}
|
|
242
|
+
edges: {
|
|
243
|
+
imports: { source_id: string; target_id: string; metadata?: any }[]
|
|
244
|
+
calls: { source_id: string; target_id: string; metadata?: any }[]
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// CIL[END chunk_id="cilgraphpage_projectgraph_1784193942"]
|
|
249
|
+
// CIL[BEGIN chunk_id="cilgraphpage_buildflowgraph_1784193942" type="function" identity="buildFlowGraph" parent="none"]
|
|
250
|
+
// CIL[DOC-MACRO purpose="Build React Flow nodes and edges from project graph data"]
|
|
251
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Transform ProjectGraph into React Flow elements per view mode"]
|
|
252
|
+
// CIL[DOC-CONTEXT module="cortex:cil-graph" layer="presentation" related_files="[]"]
|
|
253
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="{nodes: Node[]; edges: Edge[]}" errors="none" side_effects="none"]
|
|
254
|
+
// CIL[DOC-MICRO logic_summary="Constructs file and chunk nodes with styling, adds import and call edges, and applies layoutGraph to position the flow graph." notable_decisions="['Dashed edges for imports','Separate branching for files/chunks/mixed views','Labels call edges with callee_name']"]
|
|
255
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
256
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
257
|
+
// CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
258
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
259
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
260
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
261
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
262
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
263
|
+
function buildFlowGraph(graph: ProjectGraph, viewMode: ViewMode): { nodes: Node[]; edges: Edge[] } {
|
|
264
|
+
const nodes: Node[] = []
|
|
265
|
+
const edges: Edge[] = []
|
|
266
|
+
|
|
267
|
+
if (viewMode === 'files' || viewMode === 'mixed') {
|
|
268
|
+
for (const file of graph.nodes.files) {
|
|
269
|
+
nodes.push({
|
|
270
|
+
id: file.id,
|
|
271
|
+
type: 'default',
|
|
272
|
+
position: { x: 0, y: 0 },
|
|
273
|
+
data: {
|
|
274
|
+
label: file.file_path.split('/').pop() || file.file_path,
|
|
275
|
+
isFile: true,
|
|
276
|
+
file_path: file.file_path,
|
|
277
|
+
language: file.language,
|
|
278
|
+
chunk_count: file.chunk_count,
|
|
279
|
+
is_dead_code: file.is_dead_code,
|
|
280
|
+
},
|
|
281
|
+
style: {
|
|
282
|
+
background: file.is_dead_code ? '#64748B' : '#0F172A',
|
|
283
|
+
color: '#F8FAFC',
|
|
284
|
+
border: `2px solid ${file.is_dead_code ? '#475569' : '#334155'}`,
|
|
285
|
+
borderRadius: '6px',
|
|
286
|
+
fontSize: '11px',
|
|
287
|
+
fontFamily: 'monospace',
|
|
288
|
+
padding: '6px 10px',
|
|
289
|
+
width: FILE_WIDTH,
|
|
290
|
+
},
|
|
291
|
+
})
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
for (const imp of graph.edges.imports) {
|
|
295
|
+
edges.push({
|
|
296
|
+
id: `imp-${imp.source_id}-${imp.target_id}`,
|
|
297
|
+
source: imp.source_id,
|
|
298
|
+
target: imp.target_id,
|
|
299
|
+
type: 'smoothstep',
|
|
300
|
+
style: { stroke: '#334155', strokeWidth: 1.5, strokeDasharray: '4,3' },
|
|
301
|
+
markerEnd: { type: MarkerType.ArrowClosed, width: 12, height: 12, color: '#334155' },
|
|
302
|
+
label: imp.metadata?.symbols?.slice(0, 2).join(', ') || '',
|
|
303
|
+
labelStyle: { fontSize: 9, fill: '#94A3B8' },
|
|
304
|
+
})
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (viewMode === 'chunks' || viewMode === 'mixed') {
|
|
309
|
+
for (const chunk of graph.nodes.chunks) {
|
|
310
|
+
const color = chunk.is_dead_code ? '#94A3B8' : (CHUNK_TYPE_COLORS[chunk.chunk_type] || '#6366F1')
|
|
311
|
+
nodes.push({
|
|
312
|
+
id: chunk.id,
|
|
313
|
+
type: 'default',
|
|
314
|
+
position: { x: 0, y: 0 },
|
|
315
|
+
data: {
|
|
316
|
+
label: chunk.chunk_name,
|
|
317
|
+
isFile: false,
|
|
318
|
+
chunk_type: chunk.chunk_type,
|
|
319
|
+
file_path: chunk.file_path,
|
|
320
|
+
doc_confidence: chunk.doc_confidence,
|
|
321
|
+
boundary_confidence: chunk.boundary_confidence,
|
|
322
|
+
is_dead_code: chunk.is_dead_code,
|
|
323
|
+
stored_hash: chunk.stored_hash,
|
|
324
|
+
},
|
|
325
|
+
style: {
|
|
326
|
+
background: color + '22',
|
|
327
|
+
color: '#1E293B',
|
|
328
|
+
border: `2px solid ${color}`,
|
|
329
|
+
borderRadius: '8px',
|
|
330
|
+
fontSize: '11px',
|
|
331
|
+
fontFamily: 'monospace',
|
|
332
|
+
padding: '8px 12px',
|
|
333
|
+
width: NODE_WIDTH,
|
|
334
|
+
opacity: chunk.is_dead_code ? 0.5 : 1,
|
|
335
|
+
},
|
|
336
|
+
})
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
for (const call of graph.edges.calls) {
|
|
340
|
+
edges.push({
|
|
341
|
+
id: `call-${call.source_id}-${call.target_id}`,
|
|
342
|
+
source: call.source_id,
|
|
343
|
+
target: call.target_id,
|
|
344
|
+
type: 'smoothstep',
|
|
345
|
+
style: { stroke: '#6366F1', strokeWidth: 1.5 },
|
|
346
|
+
markerEnd: { type: MarkerType.ArrowClosed, width: 12, height: 12, color: '#6366F1' },
|
|
347
|
+
label: call.metadata?.callee_name || '',
|
|
348
|
+
labelStyle: { fontSize: 9, fill: '#6366F1' },
|
|
349
|
+
})
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return layoutGraph(nodes, edges)
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
// CIL[END chunk_id="cilgraphpage_buildflowgraph_1784193942"]
|
|
359
|
+
// CIL[BEGIN chunk_id="cilgraphpage_nodedetailpanel_1784193942" type="function" identity="NodeDetailPanel" parent="none"]
|
|
360
|
+
// CIL[DOC-MACRO purpose="Render metadata for a selected graph node"]
|
|
361
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Display file or chunk details and a link to the chunk contract page"]
|
|
362
|
+
// CIL[DOC-CONTEXT module="cortex:cil-graph" layer="presentation" related_files="[]"]
|
|
363
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="JSX.Element" errors="none" side_effects="none"]
|
|
364
|
+
// CIL[DOC-MICRO logic_summary="Renders a placeholder or file/chunk metadata, including badges for dead code, doc confidence, and stored hash, plus a contract link." notable_decisions="['Casts node.data as any for flexible field access']"]
|
|
365
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
366
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
367
|
+
// CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
368
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
369
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
370
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
371
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
372
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
373
|
+
function NodeDetailPanel({
|
|
374
|
+
node,
|
|
375
|
+
projectId,
|
|
376
|
+
}: {
|
|
377
|
+
node: Node | null
|
|
378
|
+
projectId: string
|
|
379
|
+
}) {
|
|
380
|
+
const appPath = (path: string) => '/spine-framework/admin' + (path.startsWith('/') ? path : '/' + path)
|
|
381
|
+
if (!node) {
|
|
382
|
+
return (
|
|
383
|
+
<div className="p-3 text-xs text-muted-foreground">
|
|
384
|
+
Click a node to inspect it
|
|
385
|
+
</div>
|
|
386
|
+
)
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
const d = node.data as any
|
|
390
|
+
|
|
391
|
+
if (d.isFile) {
|
|
392
|
+
return (
|
|
393
|
+
<div className="p-3 space-y-2 text-xs">
|
|
394
|
+
<div className="font-mono font-bold truncate" title={d.file_path}>{d.file_path}</div>
|
|
395
|
+
<div className="text-muted-foreground">{d.language} · {d.chunk_count ?? '?'} chunks</div>
|
|
396
|
+
{d.is_dead_code && <Badge variant="destructive" className="text-xs">Dead Code</Badge>}
|
|
397
|
+
</div>
|
|
398
|
+
)
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
return (
|
|
402
|
+
<div className="p-3 space-y-2 text-xs">
|
|
403
|
+
<div className="font-mono font-bold">{d.label}</div>
|
|
404
|
+
<div className="text-muted-foreground truncate">{d.file_path}</div>
|
|
405
|
+
<div className="flex gap-1 flex-wrap">
|
|
406
|
+
<Badge variant="secondary" className="text-xs">{d.chunk_type}</Badge>
|
|
407
|
+
{d.is_dead_code && <Badge variant="destructive" className="text-xs">Dead</Badge>}
|
|
408
|
+
{d.doc_confidence === 'human_verified' && <Badge variant="default" className="text-xs bg-green-600">Verified</Badge>}
|
|
409
|
+
{d.doc_confidence === 'ai_generated' && <Badge variant="outline" className="text-xs">AI Docs</Badge>}
|
|
410
|
+
{!d.stored_hash && <Badge variant="outline" className="text-xs text-amber-600 border-amber-300">No Hash</Badge>}
|
|
411
|
+
</div>
|
|
412
|
+
<a
|
|
413
|
+
href={appPath(`/cil/${projectId}/chunks/${node.id}`)}
|
|
414
|
+
className="block text-indigo-600 hover:underline font-medium"
|
|
415
|
+
>
|
|
416
|
+
Open Contract →
|
|
417
|
+
</a>
|
|
418
|
+
</div>
|
|
419
|
+
)
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
// CIL[END chunk_id="cilgraphpage_nodedetailpanel_1784193942"]
|
|
425
|
+
// CIL[BEGIN chunk_id="cilgraphpage_cilgraphpage_1784193942" type="component" identity="CILGraphPage" parent="none"]
|
|
426
|
+
// CIL[DOC-MACRO purpose="Main interactive page for the CIL project graph"]
|
|
427
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Fetch graph data, manage React Flow state, and render the graph with controls"]
|
|
428
|
+
// CIL[DOC-CONTEXT module="cortex:cil-graph" layer="presentation" related_files="[]"]
|
|
429
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="JSX.Element" errors="swallows fetch errors silently" side_effects="calls apiFetch and updates React state"]
|
|
430
|
+
// CIL[DOC-MICRO logic_summary="Loads project graph and title, builds React Flow elements, handles view mode and selection, and renders the graph, legend, and inspector panel." notable_decisions="['Silently catches API errors','Hides React Flow attribution','Refreshes on button click']"]
|
|
431
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
432
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
433
|
+
// CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
434
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
435
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
436
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
437
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
438
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
439
|
+
export default function CILGraphPage() {
|
|
440
|
+
const { id: projectId } = useParams<{ id: string }>()
|
|
441
|
+
const appPath = (path: string) => '/spine-framework/admin' + (path.startsWith('/') ? path : '/' + path)
|
|
442
|
+
const [nodes, setNodes, onNodesChange] = useNodesState([])
|
|
443
|
+
const [edges, setEdges, onEdgesChange] = useEdgesState([])
|
|
444
|
+
const [loading, setLoading] = useState(true)
|
|
445
|
+
const [viewMode, setViewMode] = useState<ViewMode>('chunks')
|
|
446
|
+
const [selectedNode, setSelectedNode] = useState<Node | null>(null)
|
|
447
|
+
const [stats, setStats] = useState({ files: 0, chunks: 0, imports: 0, calls: 0 })
|
|
448
|
+
const [projectTitle, setProjectTitle] = useState('')
|
|
449
|
+
|
|
450
|
+
const loadGraph = useCallback(async () => {
|
|
451
|
+
if (!projectId) return
|
|
452
|
+
setLoading(true)
|
|
453
|
+
try {
|
|
454
|
+
const [graphRes, projectRes] = await Promise.all([
|
|
455
|
+
apiFetch(`/api/cil-graph?action=get_project_graph&project_id=${projectId}`),
|
|
456
|
+
apiFetch(`/api/cil-project?action=get&id=${projectId}`),
|
|
457
|
+
])
|
|
458
|
+
const graphData = await graphRes.json()
|
|
459
|
+
const projectData = await projectRes.json()
|
|
460
|
+
|
|
461
|
+
const graph: ProjectGraph = graphData?.data || graphData
|
|
462
|
+
const project = projectData?.project || projectData?.data?.project
|
|
463
|
+
|
|
464
|
+
if (project?.title) setProjectTitle(project.title)
|
|
465
|
+
|
|
466
|
+
const { nodes: flowNodes, edges: flowEdges } = buildFlowGraph(graph, viewMode)
|
|
467
|
+
setNodes(flowNodes)
|
|
468
|
+
setEdges(flowEdges)
|
|
469
|
+
setStats({
|
|
470
|
+
files: graph.nodes.files.length,
|
|
471
|
+
chunks: graph.nodes.chunks.length,
|
|
472
|
+
imports: graph.edges.imports.length,
|
|
473
|
+
calls: graph.edges.calls.length,
|
|
474
|
+
})
|
|
475
|
+
} catch {
|
|
476
|
+
} finally {
|
|
477
|
+
setLoading(false)
|
|
478
|
+
}
|
|
479
|
+
}, [projectId, viewMode])
|
|
480
|
+
|
|
481
|
+
useEffect(() => { loadGraph() }, [loadGraph])
|
|
482
|
+
|
|
483
|
+
const onConnect = useCallback(
|
|
484
|
+
(params: Connection) => setEdges(eds => addEdge(params, eds)),
|
|
485
|
+
[setEdges]
|
|
486
|
+
)
|
|
487
|
+
|
|
488
|
+
if (loading) {
|
|
489
|
+
return (
|
|
490
|
+
<div className="p-6 space-y-4">
|
|
491
|
+
<Skeleton className="h-6 w-48" />
|
|
492
|
+
<Skeleton className="h-[600px] rounded-xl" />
|
|
493
|
+
</div>
|
|
494
|
+
)
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
return (
|
|
498
|
+
<div className="flex flex-col h-[calc(100vh-64px)]">
|
|
499
|
+
{}
|
|
500
|
+
<div className="flex items-center justify-between px-4 py-2 border-b bg-background shrink-0 gap-4 flex-wrap">
|
|
501
|
+
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
|
502
|
+
<a href={appPath('/cil')} className="hover:underline">Code Intelligence</a>
|
|
503
|
+
<ChevronRight className="h-3 w-3" />
|
|
504
|
+
<a href={appPath(`/cil/${projectId}/ingest`)} className="hover:underline">{projectTitle || 'Project'}</a>
|
|
505
|
+
<ChevronRight className="h-3 w-3" />
|
|
506
|
+
<span>Graph</span>
|
|
507
|
+
</div>
|
|
508
|
+
|
|
509
|
+
<div className="flex items-center gap-2">
|
|
510
|
+
<div className="flex items-center gap-1.5 text-xs text-muted-foreground">
|
|
511
|
+
<span className="font-mono">{stats.files} files</span>
|
|
512
|
+
<span>·</span>
|
|
513
|
+
<span className="font-mono">{stats.chunks} chunks</span>
|
|
514
|
+
<span>·</span>
|
|
515
|
+
<span className="font-mono">{stats.calls} calls</span>
|
|
516
|
+
<span>·</span>
|
|
517
|
+
<span className="font-mono">{stats.imports} imports</span>
|
|
518
|
+
</div>
|
|
519
|
+
|
|
520
|
+
<Select value={viewMode} onValueChange={v => setViewMode(v as ViewMode)}>
|
|
521
|
+
<SelectTrigger className="h-7 w-28 text-xs">
|
|
522
|
+
<Layers className="h-3 w-3 mr-1" />
|
|
523
|
+
<SelectValue />
|
|
524
|
+
</SelectTrigger>
|
|
525
|
+
<SelectContent>
|
|
526
|
+
<SelectItem value="chunks">Chunks</SelectItem>
|
|
527
|
+
<SelectItem value="files">Files</SelectItem>
|
|
528
|
+
<SelectItem value="mixed">Mixed</SelectItem>
|
|
529
|
+
</SelectContent>
|
|
530
|
+
</Select>
|
|
531
|
+
|
|
532
|
+
<Button size="sm" variant="outline" onClick={loadGraph} className="h-7 text-xs">
|
|
533
|
+
<RefreshCw className="h-3 w-3 mr-1" />
|
|
534
|
+
Refresh
|
|
535
|
+
</Button>
|
|
536
|
+
</div>
|
|
537
|
+
</div>
|
|
538
|
+
|
|
539
|
+
<PageInstructions
|
|
540
|
+
description="Explore the file and chunk call graph for a project."
|
|
541
|
+
sections={[
|
|
542
|
+
{ title: 'What this page is for', content: 'This page visualizes import links between files and call links between chunks for the selected CIL project.' },
|
|
543
|
+
{ title: 'How to read this page', content: 'The React Flow canvas shows nodes and edges. The legend explains colors by chunk type. The Inspector panel on the right displays details for the selected node.' },
|
|
544
|
+
{ title: 'How to use this page', content: 'Switch the view mode to files or chunks. Click a node to see its details in the inspector. Pan, zoom, and use the minimap to navigate large graphs.' },
|
|
545
|
+
{ title: 'Important notes', content: 'The graph is only available after Pass 1 and Pass 2 ingestion complete. Empty graphs mean no imports or calls were detected yet.' },
|
|
546
|
+
]}
|
|
547
|
+
/>
|
|
548
|
+
|
|
549
|
+
{}
|
|
550
|
+
<div className="flex flex-1 min-h-0">
|
|
551
|
+
<div className="flex-1">
|
|
552
|
+
{nodes.length === 0 ? (
|
|
553
|
+
<div className="flex items-center justify-center h-full text-muted-foreground text-sm">
|
|
554
|
+
<div className="text-center space-y-2">
|
|
555
|
+
<ZoomIn className="h-10 w-10 mx-auto opacity-20" />
|
|
556
|
+
<p>No {viewMode === 'files' ? 'files' : 'chunks'} found.</p>
|
|
557
|
+
<p className="text-xs">Run Pass 1 + Pass 2 ingestion first.</p>
|
|
558
|
+
</div>
|
|
559
|
+
</div>
|
|
560
|
+
) : (
|
|
561
|
+
<ReactFlow
|
|
562
|
+
nodes={nodes}
|
|
563
|
+
edges={edges}
|
|
564
|
+
onNodesChange={onNodesChange}
|
|
565
|
+
onEdgesChange={onEdgesChange}
|
|
566
|
+
onConnect={onConnect}
|
|
567
|
+
onNodeClick={(_evt, node) => setSelectedNode(node)}
|
|
568
|
+
fitView
|
|
569
|
+
fitViewOptions={{ padding: 0.15 }}
|
|
570
|
+
minZoom={0.1}
|
|
571
|
+
maxZoom={2}
|
|
572
|
+
proOptions={{ hideAttribution: true }}
|
|
573
|
+
>
|
|
574
|
+
<Background color="#E2E8F0" gap={20} size={1} />
|
|
575
|
+
<Controls />
|
|
576
|
+
<MiniMap
|
|
577
|
+
nodeColor={nodeColor}
|
|
578
|
+
style={{ background: '#F8FAFC', border: '1px solid #E2E8F0' }}
|
|
579
|
+
pannable
|
|
580
|
+
zoomable
|
|
581
|
+
/>
|
|
582
|
+
|
|
583
|
+
{}
|
|
584
|
+
<Panel position="bottom-left">
|
|
585
|
+
<div className="bg-background/90 backdrop-blur border rounded-lg p-2 text-xs space-y-1 shadow-sm">
|
|
586
|
+
{Object.entries(CHUNK_TYPE_COLORS).map(([type, color]) => (
|
|
587
|
+
<div key={type} className="flex items-center gap-1.5">
|
|
588
|
+
<div className="w-3 h-3 rounded-sm shrink-0" style={{ background: color + '44', border: `1.5px solid ${color}` }} />
|
|
589
|
+
<span className="text-muted-foreground">{type}</span>
|
|
590
|
+
</div>
|
|
591
|
+
))}
|
|
592
|
+
{viewMode !== 'chunks' && (
|
|
593
|
+
<div className="flex items-center gap-1.5 pt-1 border-t">
|
|
594
|
+
<div className="w-3 h-3 rounded-sm shrink-0 bg-slate-900" />
|
|
595
|
+
<span className="text-muted-foreground">file</span>
|
|
596
|
+
</div>
|
|
597
|
+
)}
|
|
598
|
+
</div>
|
|
599
|
+
</Panel>
|
|
600
|
+
</ReactFlow>
|
|
601
|
+
)}
|
|
602
|
+
</div>
|
|
603
|
+
|
|
604
|
+
{}
|
|
605
|
+
<div className="w-56 border-l bg-muted/30 shrink-0 overflow-y-auto">
|
|
606
|
+
<div className="p-2 border-b bg-background">
|
|
607
|
+
<p className="text-xs font-medium text-muted-foreground uppercase tracking-wide">Inspector</p>
|
|
608
|
+
</div>
|
|
609
|
+
<NodeDetailPanel node={selectedNode} projectId={projectId!} />
|
|
610
|
+
</div>
|
|
611
|
+
</div>
|
|
612
|
+
</div>
|
|
613
|
+
)
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// CIL[END chunk_id="cilgraphpage_cilgraphpage_1784193942"]
|