spine-framework 0.3.145 → 0.4.1
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/.env.example +76 -0
- package/.framework/.spine-manifest.json +19 -0
- package/.framework/cli/commands/agents.ts +61 -33
- package/.framework/cli/commands/auth.ts +60 -28
- package/.framework/cli/commands/create-app.ts +212 -80
- package/.framework/cli/commands/dev.ts +184 -68
- package/.framework/cli/commands/doctor.ts +324 -152
- package/.framework/cli/commands/generate.ts +119 -68
- package/.framework/cli/commands/init.ts +141 -242
- package/.framework/cli/commands/install-app.ts +1336 -314
- package/.framework/cli/commands/items.ts +31 -29
- package/.framework/cli/commands/migrate.ts +299 -156
- package/.framework/cli/commands/migrations.ts +62 -30
- package/.framework/cli/commands/pipelines.ts +31 -29
- package/.framework/cli/commands/status.ts +105 -45
- package/.framework/cli/commands/system.ts +47 -42
- package/.framework/cli/commands/test.ts +161 -102
- package/.framework/cli/commands/upgrade.ts +260 -0
- package/.framework/cli/commands/validate-app.ts +517 -161
- package/.framework/cli/context.ts +117 -85
- package/.framework/cli/env-loader.ts +74 -43
- package/.framework/cli/index.ts +70 -46
- package/.framework/cli/lib/project-files.ts +404 -0
- package/.framework/docs/guides/testing-guide.md +1 -1
- package/.framework/docs/runtime-types.md +72 -72
- package/.framework/functions/_shared/access.ts +84 -0
- package/.framework/functions/_shared/agent-runner.ts +5067 -1026
- package/.framework/functions/_shared/app-manifest.ts +214 -94
- package/.framework/functions/_shared/ast.ts +214 -0
- package/.framework/functions/_shared/audit.ts +91 -55
- package/.framework/functions/_shared/cil.ts +368 -127
- package/.framework/functions/_shared/db.ts +337 -68
- package/.framework/functions/_shared/funnel.ts +228 -0
- package/.framework/functions/_shared/geo.ts +105 -0
- package/.framework/functions/_shared/hash-api-key.ts +94 -17
- package/.framework/functions/_shared/index.ts +22 -224
- package/.framework/functions/_shared/kb.ts +832 -58
- package/.framework/functions/_shared/llm.ts +118 -18
- package/.framework/functions/_shared/logging.ts +317 -19
- package/.framework/functions/_shared/middleware.ts +701 -131
- package/.framework/functions/_shared/notify.ts +70 -0
- package/.framework/functions/_shared/outcomes.ts +34 -19
- package/.framework/functions/_shared/permissions.ts +501 -315
- package/.framework/functions/_shared/pipeline-runner.ts +704 -155
- package/.framework/functions/_shared/principal.ts +436 -263
- package/.framework/functions/_shared/rate-limit.ts +233 -0
- package/.framework/functions/_shared/resolve-credentials.ts +86 -19
- package/.framework/functions/_shared/resolve-ids.ts +203 -139
- package/.framework/functions/_shared/retry-deliveries.ts +51 -16
- package/.framework/functions/_shared/schema-utils.ts +602 -521
- package/.framework/functions/_shared/security.ts +345 -0
- package/.framework/functions/_shared/testing.ts +197 -172
- package/.framework/functions/_shared/tracing.ts +351 -21
- package/.framework/functions/_shared/trigger-engine.ts +425 -136
- package/.framework/functions/_shared/webhook-registration.ts +71 -70
- package/.framework/functions/_shared/webhook-registry.ts +126 -83
- package/.framework/functions/account-nodes.ts +30 -30
- package/.framework/functions/adapters/generic-webhook-inbound.ts +49 -16
- package/.framework/functions/adapters/generic-webhook-outbound.ts +17 -17
- package/.framework/functions/adapters/openai-outbound.ts +15 -16
- package/.framework/functions/admin-data.ts +596 -173
- package/.framework/functions/admin-funnel.ts +64 -60
- package/.framework/functions/admin-install-funnel.ts +84 -66
- package/.framework/functions/admin-signals.ts +69 -51
- package/.framework/functions/ai-agents.ts +431 -106
- package/.framework/functions/ai-interactions.ts +186 -112
- package/.framework/functions/api-keys.ts +107 -107
- package/.framework/functions/apps.ts +154 -136
- package/.framework/functions/auth.ts +83 -65
- package/.framework/functions/cil-agent-ingest.ts +189 -232
- package/.framework/functions/cil-agent.ts +433 -177
- package/.framework/functions/cil-callmap.ts +642 -430
- package/.framework/functions/cil-config.ts +139 -135
- package/.framework/functions/cil-context.ts +214 -127
- package/.framework/functions/cil-doc.ts +587 -458
- package/.framework/functions/cil-embeddings.ts +453 -364
- package/.framework/functions/cil-graph.ts +427 -142
- package/.framework/functions/cil-ingest.ts +1418 -1154
- package/.framework/functions/cil-pipeline.ts +276 -21
- package/.framework/functions/cil-project.ts +659 -132
- package/.framework/functions/cil-validate.ts +198 -164
- package/.framework/functions/debug-auth.ts +57 -55
- package/.framework/functions/deliveries.ts +80 -21
- package/.framework/functions/embeddings.ts +1023 -318
- package/.framework/functions/eval-harness.ts +146 -108
- package/.framework/functions/integration-outbound.ts +205 -75
- package/.framework/functions/integration-routes.ts +128 -23
- package/.framework/functions/integrations.ts +125 -100
- package/.framework/functions/invites.ts +1095 -460
- package/.framework/functions/item-progress.ts +158 -102
- package/.framework/functions/kb.ts +34 -10
- package/.framework/functions/logs.ts +133 -133
- package/.framework/functions/observability.ts +152 -122
- package/.framework/functions/pipeline-executions.ts +147 -132
- package/.framework/functions/pipelines.ts +134 -119
- package/.framework/functions/prompt-configs.ts +96 -80
- package/.framework/functions/roles.ts +112 -82
- package/.framework/functions/security.ts +450 -0
- package/.framework/functions/system-cron.ts +117 -80
- package/.framework/functions/system.ts +158 -98
- package/.framework/functions/tests.ts +29 -29
- package/.framework/functions/timers.ts +94 -95
- package/.framework/functions/trigger-scheduler.ts +10 -0
- package/.framework/functions/triggers.ts +179 -149
- package/.framework/functions/types.ts +137 -125
- package/.framework/mcp/index.ts +133 -0
- package/.framework/mcp/load-env.ts +60 -0
- package/.framework/mcp/shared/app-manifest.ts +275 -0
- package/.framework/mcp/shared/db.ts +477 -0
- package/.framework/mcp/shared/kb.ts +118 -0
- package/.framework/mcp/tools/architect.ts +431 -0
- package/.framework/mcp/tools/cil/context.ts +345 -0
- package/.framework/mcp/tools/cil/graph.ts +242 -0
- package/.framework/mcp/tools/cil/ingest.ts +1217 -0
- package/.framework/mcp/tools/cil/pipeline-orchestrator.ts +693 -0
- package/.framework/mcp/tools/cil/pipeline.ts +767 -0
- package/.framework/mcp/tools/cil/project.ts +791 -0
- package/.framework/mcp/tools/cil/retrieval.ts +336 -0
- package/.framework/mcp/tools/cil/search-core.ts +454 -0
- package/.framework/mcp/tools/cil/search.ts +97 -0
- package/.framework/mcp/tools/cil/suggest.ts +186 -0
- package/.framework/mcp/tools/cil/validate.ts +1369 -0
- package/.framework/mcp/tools/kb/delete.ts +139 -0
- package/.framework/mcp/tools/kb/index.ts +52 -0
- package/.framework/mcp/tools/kb/ingest.ts +84 -0
- package/.framework/mcp/tools/kb/list-types.ts +102 -0
- package/.framework/mcp/tools/kb/publish.ts +100 -0
- package/.framework/mcp/tools/kb/reindex.ts +86 -0
- package/.framework/mcp/tools/kb/revoke.ts +85 -0
- package/.framework/mcp/tools/kb/search.ts +101 -0
- package/.framework/mcp/tools/kb/upsert.ts +125 -0
- package/.framework/mcp/tools/observability.ts +510 -0
- package/.framework/migrations/001_core_schema.sql +15 -0
- package/.framework/migrations/002_core_rls_and_functions.sql +15 -0
- package/.framework/migrations/003_core_system_data.sql +16 -1
- package/.framework/migrations/004_core_rpc_and_broker.sql +17 -1
- package/.framework/migrations/005_core_observability.sql +17 -1
- package/.framework/migrations/006_security_hardening_rls.sql +15 -0
- package/.framework/migrations/007_kb_article_list.sql +17 -1
- package/.framework/migrations/008_items_target.sql +15 -0
- package/.framework/migrations/009_roles_slug_unique.sql +15 -0
- package/.framework/migrations/010_auth_user_trigger.sql +15 -0
- package/.framework/migrations/011_spine_system_account.sql +16 -0
- package/.framework/migrations/012_service_role_grants.sql +16 -0
- package/.framework/migrations/013_get_account_apps_role_filter.sql +15 -0
- package/.framework/migrations/014_apps_required_roles.sql +16 -0
- package/.framework/migrations/015_types_kind_slug_unique.sql +15 -0
- package/.framework/migrations/016_cil_types.sql +281 -0
- package/.framework/migrations/017_cil_stable_ids.sql +37 -0
- package/.framework/migrations/018_runtime_tables.sql +129 -0
- package/.framework/migrations/019_agent_prompt_columns.sql +56 -0
- package/.framework/migrations/020_schema_reconciliation.sql +67 -0
- package/.framework/migrations/021_kb_embedding_lifecycle.sql +31 -0
- package/.framework/migrations/032_cil_status_migration.sql +73 -0
- package/.framework/migrations/033_cil_versioning.sql +73 -0
- package/.framework/migrations/034_match_embeddings_knn.sql +115 -0
- package/.framework/migrations/035_rate_limits.sql +55 -0
- package/.framework/migrations/036_demo_record_flags.sql +72 -0
- package/.framework/migrations/037_kb_types_canonical.sql +244 -0
- package/.framework/migrations/038_drop_demo_record_flags.sql +38 -0
- package/.framework/migrations/042_registration_hierarchy.sql +309 -0
- package/.framework/migrations/043_policy_actor_cleanup.sql +39 -0
- package/.framework/migrations/044_match_embeddings_filtered_knn.sql +151 -0
- package/.framework/migrations/045_security_critical_rls.sql +139 -0
- package/.framework/migrations/046_security_missing_rls.sql +79 -0
- package/.framework/migrations/047_people_updated_by.sql +27 -0
- package/.framework/migrations/048_watcher_last_seen_at.sql +24 -0
- package/.framework/migrations/049_security_blocklist.sql +148 -0
- package/.framework/migrations/050_notifications.sql +49 -0
- package/.framework/migrations/051_message_agent_fields.sql +74 -0
- package/.framework/migrations/052_registration_security.sql +421 -0
- package/.framework/migrations/053_builtin_action_seeds.sql +66 -0
- package/.framework/migrations/054_kb_ingest_lease.sql +157 -0
- package/.framework/migrations/055_type_id_drift_reconciliation.sql +33 -0
- package/.framework/migrations/056_slug_column_reconciliation.sql +38 -0
- package/.framework/migrations/057_pipelines_slug_identity.sql +14 -0
- package/.framework/migrations/058_account_data_field_declarations.sql +53 -0
- package/.framework/migrations/059_registration_placement_fixes.sql +269 -0
- package/.framework/migrations/060_account_person_record_permissions.sql +38 -0
- package/.framework/migrations/061_fk_dedup.sql +32 -0
- package/.framework/public/spine-logo.svg +10 -3
- package/.framework/scripts/app-install-cli.ts +190 -93
- package/.framework/scripts/assemble-frontend.sh +127 -44
- package/.framework/scripts/assemble-functions.sh +128 -30
- package/.framework/scripts/boundary-check.sh +6 -2
- package/.framework/scripts/build-manifest.sh +24 -68
- package/.framework/scripts/check-core-integrity.sh +15 -76
- package/.framework/scripts/checksum-manifest.mts +343 -0
- package/.framework/scripts/cil-migrate-markers.ts +403 -0
- package/.framework/scripts/fix-cil-markers.mjs +176 -0
- package/.framework/scripts/verify-integrity.sh +21 -57
- package/.framework/scripts/verify-manifest.mts +305 -0
- package/.framework/seeds/types/funnel_signal_use.json +74 -21
- package/.framework/seeds/types/spine_instance.json +73 -21
- package/.framework/src/App.tsx +118 -72
- package/.framework/src/apps/admin/index.tsx +855 -58
- package/.framework/src/components/AppWrapper.tsx +43 -45
- package/.framework/src/components/CustomAppLoader.tsx +160 -116
- package/.framework/src/components/admin/AdminListPage.tsx +46 -44
- package/.framework/src/components/admin/AdminSidebar.tsx +57 -47
- package/.framework/src/components/admin/AdminStatsCard.tsx +46 -44
- package/.framework/src/components/admin/PageInstructions.tsx +98 -2
- package/.framework/src/components/admin/SortableTableHeader.tsx +44 -45
- package/.framework/src/components/app-shell/GenericAppShell.tsx +64 -65
- package/.framework/src/components/app-shell/GenericDetailPage.tsx +44 -47
- package/.framework/src/components/app-shell/GenericListPage.tsx +45 -49
- package/.framework/src/components/app-sidebar.tsx +42 -45
- package/.framework/src/components/auth/ProtectedRoute.tsx +48 -41
- package/.framework/src/components/auth/TurnstileWidget.tsx +27 -0
- package/.framework/src/components/kb/KBArticleEditor.tsx +231 -22
- package/.framework/src/components/kb/KBArticleList.tsx +251 -10
- package/.framework/src/components/layout/AppShell.tsx +51 -45
- package/.framework/src/components/layout/Header.tsx +42 -43
- package/.framework/src/components/layout/Layout.tsx +46 -46
- package/.framework/src/components/layout/Sidebar.tsx +196 -96
- package/.framework/src/components/runtime/DataDetailHeader.tsx +55 -30
- package/.framework/src/components/runtime/DataDetailPage.tsx +31 -269
- package/.framework/src/components/runtime/DataFilters.tsx +49 -74
- package/.framework/src/components/runtime/DataHeader.tsx +53 -32
- package/.framework/src/components/runtime/DataListPage.tsx +51 -155
- package/.framework/src/components/runtime/DataStats.tsx +66 -44
- package/.framework/src/components/runtime/DataTable.tsx +49 -149
- package/.framework/src/components/runtime/SchemaDetailForm.tsx +45 -75
- package/.framework/src/components/runtime/index.ts +119 -16
- package/.framework/src/components/search-form.tsx +46 -29
- package/.framework/src/components/shared/AgentView.tsx +65 -48
- package/.framework/src/components/shared/FieldRenderer.tsx +144 -50
- package/.framework/src/components/shared/InviteManager.tsx +207 -97
- package/.framework/src/components/shared/MemberList.tsx +97 -0
- package/.framework/src/components/shared/SchemaFields.tsx +107 -86
- package/.framework/src/components/ui/DataTable.tsx +80 -68
- package/.framework/src/components/ui/Form.tsx +157 -146
- package/.framework/src/components/ui/ItemCard.tsx +74 -67
- package/.framework/src/components/ui/ItemListView.tsx +73 -68
- package/.framework/src/components/ui/LoadingSpinner.tsx +43 -48
- package/.framework/src/components/ui/Modal.tsx +78 -68
- package/.framework/src/components/ui/RichTextEditor.tsx +89 -69
- package/.framework/src/components/ui/accordion.tsx +85 -86
- package/.framework/src/components/ui/alert-dialog.tsx +197 -184
- package/.framework/src/components/ui/alert.tsx +105 -94
- package/.framework/src/components/ui/aspect-ratio.tsx +57 -43
- package/.framework/src/components/ui/avatar.tsx +122 -107
- package/.framework/src/components/ui/badge.tsx +60 -55
- package/.framework/src/components/ui/breadcrumb.tsx +127 -128
- package/.framework/src/components/ui/button-group.tsx +86 -72
- package/.framework/src/components/ui/button.tsx +71 -50
- package/.framework/src/components/ui/calendar.tsx +72 -57
- package/.framework/src/components/ui/card.tsx +136 -129
- package/.framework/src/components/ui/carousel.tsx +226 -107
- package/.framework/src/components/ui/chart.tsx +252 -147
- package/.framework/src/components/ui/checkbox.tsx +43 -44
- package/.framework/src/components/ui/collapsible.tsx +86 -71
- package/.framework/src/components/ui/combobox.tsx +282 -249
- package/.framework/src/components/ui/command.tsx +158 -146
- package/.framework/src/components/ui/context-menu.tsx +239 -240
- package/.framework/src/components/ui/dialog.tsx +174 -157
- package/.framework/src/components/ui/direction.tsx +72 -56
- package/.framework/src/components/ui/drawer.tsx +168 -169
- package/.framework/src/components/ui/dropdown-menu.tsx +254 -223
- package/.framework/src/components/ui/empty.tsx +131 -120
- package/.framework/src/components/ui/field.tsx +205 -173
- package/.framework/src/components/ui/hover-card.tsx +71 -72
- package/.framework/src/components/ui/input-group.tsx +148 -133
- package/.framework/src/components/ui/input-otp.tsx +99 -86
- package/.framework/src/components/ui/input.tsx +43 -41
- package/.framework/src/components/ui/item.tsx +207 -185
- package/.framework/src/components/ui/kbd.tsx +57 -56
- package/.framework/src/components/ui/label.tsx +45 -41
- package/.framework/src/components/ui/menubar.tsx +268 -236
- package/.framework/src/components/ui/native-select.tsx +85 -86
- package/.framework/src/components/ui/navigation-menu.tsx +166 -156
- package/.framework/src/components/ui/pagination.tsx +131 -141
- package/.framework/src/components/ui/popover.tsx +125 -128
- package/.framework/src/components/ui/progress.tsx +47 -44
- package/.framework/src/components/ui/radio-group.tsx +60 -55
- package/.framework/src/components/ui/resizable.tsx +85 -72
- package/.framework/src/components/ui/scroll-area.tsx +57 -58
- package/.framework/src/components/ui/select.tsx +182 -169
- package/.framework/src/components/ui/separator.tsx +42 -43
- package/.framework/src/components/ui/sheet.tsx +170 -159
- package/.framework/src/components/ui/sidebar.tsx +395 -398
- package/.framework/src/components/ui/skeleton.tsx +42 -43
- package/.framework/src/components/ui/slider.tsx +61 -44
- package/.framework/src/components/ui/sonner.tsx +44 -44
- package/.framework/src/components/ui/spinner.tsx +47 -42
- package/.framework/src/components/ui/switch.tsx +56 -42
- package/.framework/src/components/ui/table-primitives.tsx +272 -132
- package/.framework/src/components/ui/table.tsx +140 -142
- package/.framework/src/components/ui/tabs.tsx +110 -93
- package/.framework/src/components/ui/textarea.tsx +43 -44
- package/.framework/src/components/ui/toggle-group.tsx +87 -71
- package/.framework/src/components/ui/toggle.tsx +56 -56
- package/.framework/src/components/ui/tooltip.tsx +99 -85
- package/.framework/src/contexts/AppContext.tsx +166 -114
- package/.framework/src/contexts/AuthContext.tsx +232 -137
- package/.framework/src/hooks/use-mobile.ts +43 -44
- package/.framework/src/hooks/useApi.ts +185 -172
- package/.framework/src/hooks/useAppPath.ts +31 -29
- package/.framework/src/hooks/useApps.ts +77 -42
- package/.framework/src/hooks/useEntityList.ts +66 -29
- package/.framework/src/hooks/useEntityRecord.ts +76 -32
- package/.framework/src/hooks/useForm.ts +62 -30
- package/.framework/src/hooks/useListSchema.ts +60 -43
- package/.framework/src/hooks/useSchemaRecord.ts +115 -95
- package/.framework/src/lib/api.ts +258 -134
- package/.framework/src/lib/registration.ts +181 -0
- package/.framework/src/lib/supabase.ts +118 -81
- package/.framework/src/lib/utils.ts +266 -266
- package/.framework/src/main.tsx +43 -44
- package/.framework/src/pages/DashboardPage.tsx +44 -43
- package/.framework/src/pages/NoAppPage.tsx +50 -0
- package/.framework/src/pages/NotFoundPage.tsx +32 -29
- package/.framework/src/pages/SetupPage.tsx +34 -33
- package/.framework/src/pages/admin/AIAgentDetailPage.tsx +69 -58
- package/.framework/src/pages/admin/AIAgentsPage.tsx +43 -40
- package/.framework/src/pages/admin/APIKeyDetailPage.tsx +63 -55
- package/.framework/src/pages/admin/APIKeysPage.tsx +44 -42
- package/.framework/src/pages/admin/AlertsConfigPage.tsx +117 -94
- package/.framework/src/pages/admin/AppDetailPage.tsx +48 -42
- package/.framework/src/pages/admin/AppsPage.tsx +45 -42
- package/.framework/src/pages/admin/DeliveriesPage.tsx +49 -17
- package/.framework/src/pages/admin/DesignedPage.tsx +31 -30
- package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +58 -0
- package/.framework/src/pages/admin/EmbeddingsPage.tsx +49 -0
- package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +31 -29
- package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +46 -29
- package/.framework/src/pages/admin/IntegratedDashboard.tsx +32 -29
- package/.framework/src/pages/admin/IntegrationDetailPage.tsx +68 -55
- package/.framework/src/pages/admin/IntegrationsPage.tsx +45 -42
- package/.framework/src/pages/admin/InvitesPage.tsx +60 -44
- package/.framework/src/pages/admin/LogsPage.tsx +87 -137
- package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +31 -29
- package/.framework/src/pages/admin/ObservabilityDashboard.tsx +150 -89
- package/.framework/src/pages/admin/PipelineDetailPage.tsx +77 -104
- package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +44 -43
- package/.framework/src/pages/admin/PipelinesPage.tsx +59 -145
- package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +53 -42
- package/.framework/src/pages/admin/PromptConfigsPage.tsx +47 -117
- package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +31 -44
- package/.framework/src/pages/admin/RoleDetailPage.tsx +49 -92
- package/.framework/src/pages/admin/RolesPage.tsx +47 -164
- package/.framework/src/pages/admin/SecurityPage.tsx +310 -0
- package/.framework/src/pages/admin/SelectTestPage.tsx +30 -32
- package/.framework/src/pages/admin/ShadcnTestPage.tsx +37 -44
- package/.framework/src/pages/admin/SimpleDashboard.tsx +32 -44
- package/.framework/src/pages/admin/TestRunDetailPage.tsx +97 -44
- package/.framework/src/pages/admin/TestingDashboard.tsx +126 -71
- package/.framework/src/pages/admin/TimerDetailPage.tsx +67 -55
- package/.framework/src/pages/admin/TimersPage.tsx +44 -42
- package/.framework/src/pages/admin/TriggerDetailPage.tsx +47 -42
- package/.framework/src/pages/admin/TriggersPage.tsx +58 -57
- package/.framework/src/pages/admin/TypeDetailPage.tsx +91 -55
- package/.framework/src/pages/admin/TypesPage.tsx +45 -42
- package/.framework/src/pages/admin/cil/CILAgentPage.tsx +258 -128
- package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +127 -123
- package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +308 -235
- package/.framework/src/pages/admin/cil/CILFileListPage.tsx +159 -110
- package/.framework/src/pages/admin/cil/CILFileSelectPage.tsx +432 -0
- package/.framework/src/pages/admin/cil/CILGraphPage.tsx +200 -178
- package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +286 -239
- package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +211 -90
- package/.framework/src/pages/admin/cil/CILSearchPage.tsx +156 -143
- package/.framework/src/pages/admin/cil/CILSuggestionsPage.tsx +379 -0
- package/.framework/src/pages/admin/cil/CILVersionsPage.tsx +337 -0
- package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +219 -214
- package/.framework/src/pages/admin/kb/KBAdminPage.tsx +64 -0
- package/.framework/src/pages/auth/AuthConfirmPage.tsx +135 -65
- package/.framework/src/pages/auth/ForgotPasswordPage.tsx +39 -31
- package/.framework/src/pages/auth/LoginPage.tsx +38 -32
- package/.framework/src/pages/auth/PendingApprovalPage.tsx +31 -28
- package/.framework/src/pages/auth/RegisterPage.tsx +429 -155
- package/.framework/src/pages/spine-framework/APIPage.tsx +33 -30
- package/.framework/src/pages/spine-framework/CLIPage.tsx +32 -30
- package/.framework/src/types/auth.ts +101 -93
- package/.framework/src/types/types.ts +283 -262
- package/.framework/templates/project.json +87 -0
- package/.framework/templates/spine.config.neutral.json +7 -0
- package/.framework/tests/api/api-surface.test.ts +381 -0
- package/.framework/tests/fixtures/seed.ts +427 -0
- package/.framework/tests/fixtures/teardown.ts +228 -0
- package/.framework/tests/reporter.ts +351 -0
- package/.framework/tests/setup.ts +135 -0
- package/.framework/tests/ui/ui-sweep.ts +278 -0
- package/.framework/tests/unit/admin-data-logger.test.ts +310 -0
- package/.framework/tests/unit/agent-runner.test.ts +2389 -0
- package/.framework/tests/unit/ai-interactions.test.ts +81 -0
- package/.framework/tests/unit/app-manifest.test.ts +359 -0
- package/.framework/tests/unit/assembly-scripts.test.ts +172 -0
- package/.framework/tests/unit/cil-determinism.test.ts +85 -0
- package/.framework/tests/unit/core-isolation.test.ts +153 -0
- package/.framework/tests/unit/funnel-signals.test.ts +135 -0
- package/.framework/tests/unit/install-app.test.ts +1759 -0
- package/.framework/tests/unit/invites-security.test.ts +572 -0
- package/.framework/tests/unit/kb-ingest-lease.test.ts +287 -0
- package/.framework/tests/unit/kb-search.test.ts +119 -0
- package/.framework/tests/unit/migrate.test.ts +509 -0
- package/.framework/tests/unit/notify.test.ts +136 -0
- package/.framework/tests/unit/permissions.test.ts +269 -0
- package/.framework/tests/unit/pipeline-runner.test.ts +755 -0
- package/.framework/tests/unit/principal-cache.test.ts +138 -0
- package/.framework/tests/unit/retrieval-golden.test.ts +520 -0
- package/.framework/tests/unit/runtime-isolation.test.ts +642 -0
- package/.framework/tests/unit/schema-utils.test.ts +225 -0
- package/.framework/tests/unit/trigger-engine.test.ts +513 -0
- package/.framework/tests/unit/validate-app.test.ts +527 -0
- package/README.md +34 -3
- package/bin/spine-framework.cjs +1 -0
- package/config/tailwind.config.cjs +7 -0
- package/config/tsconfig.functions.json +42 -0
- package/config/tsconfig.json +37 -9
- package/config/vite.config.ts +31 -2
- package/netlify.toml +31 -3
- package/package.json +46 -29
- package/scripts/assemble-frontend.sh +127 -44
- package/scripts/assemble-functions.sh +127 -29
- package/scripts/boundary-check.sh +6 -2
- package/scripts/build-manifest.sh +24 -68
- package/scripts/checksum-manifest.mts +345 -0
- package/scripts/dev-clean.sh +86 -0
- package/scripts/dev-netlify.sh +49 -0
- package/scripts/netlify-dev-wrapper.sh +2 -0
- package/scripts/verify-install.ts +358 -0
- package/scripts/verify-integrity.sh +21 -57
- package/scripts/verify-manifest.mts +305 -0
- package/templates/project/gitignore +45 -0
- package/{config → templates/project}/package-lock.json +22335 -9366
- package/vitest.config.ts +46 -0
- package/.framework/public/spine.config.json +0 -91
- package/config/deno.lock +0 -108
- package/config/tsconfig.node.tsbuildinfo +0 -1
- package/config/tsconfig.tsbuildinfo +0 -1
- package/config/vite.config.d.ts +0 -2
- package/custom/.devin/AGENT.md +0 -357
- package/custom/.devin/skills/install-app/SKILL.md +0 -39
- package/custom/.devin/skills/spine-workbench-discovery/SKILL.md +0 -39
- package/custom/.devin/skills/spine-workbench-idea/SKILL.md +0 -36
- package/custom/.devin/skills/spine-workbench-implement/SKILL.md +0 -46
- package/custom/.devin/skills/spine-workbench-initiative/SKILL.md +0 -28
- package/custom/.devin/skills/spine-workbench-plan/SKILL.md +0 -38
- package/custom/.devin/workflows/app-install.yaml +0 -83
- package/custom/README.md +0 -79
- package/docs/README.md +0 -15
- package/scripts/app-install-cli.ts +0 -286
- package/scripts/check-core-integrity.sh +0 -82
- package/scripts/ingest-chunks.cjs +0 -202
- package/scripts/kb-chunk-parser.cjs +0 -312
- package/scripts/kb-chunk-parser.ts +0 -330
- package/scripts/kb-ingest-docs.ts +0 -203
- package/scripts/load-test-app-install.ts +0 -484
- package/scripts/test-login.js +0 -33
- package/spine.config.json +0 -91
|
@@ -1,18 +1,13 @@
|
|
|
1
|
-
// CIL[BEGIN
|
|
2
|
-
// CIL[DOC-MACRO purpose="
|
|
3
|
-
// CIL[DOC-RESPONSIBILITY responsibility="
|
|
4
|
-
// CIL[DOC-CONTEXT module="
|
|
5
|
-
// CIL[DOC-CONTRACT inputs="
|
|
6
|
-
// CIL[DOC-MICRO logic_summary="
|
|
7
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.
|
|
1
|
+
// CIL[BEGIN stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/src/pages/admin/cil/CILAgentPage.tsx"]
|
|
2
|
+
// CIL[DOC-MACRO purpose="Chat interface for the CIL agent that answers natural-language questions about indexed code"]
|
|
3
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Provide a React page that lets users ask the CIL agent questions and view grounded answers with source chunk references"]
|
|
4
|
+
// CIL[DOC-CONTEXT module=".framework/src/pages/admin/cil" layer="admin-ui" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/badge.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/components/ui/textarea.tsx,.framework/src/lib/api.ts"]
|
|
5
|
+
// CIL[DOC-CONTRACT inputs="project_id from URL and user question" outputs="Rendered chat UI with messages and source links" errors="API request failures render error message in chat" side_effects="Calls /api/cil-agent?action=prepare, /api/ai-agents?action=run, /api/admin-data?entity=messages, and /api/cil-project"]
|
|
6
|
+
// CIL[DOC-MICRO logic_summary="Imports dependencies, defines message types, markdown rendering, message bubble, suggestions, and the main page component." notable_decisions="[]"]
|
|
7
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
8
8
|
// CIL[DOC-STABILITY stability="stable"]
|
|
9
9
|
// CIL[DOC-AUDIENCE audience="developer"]
|
|
10
|
-
|
|
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"]
|
|
10
|
+
|
|
16
11
|
import { useState, useRef, useEffect, useCallback } from 'react'
|
|
17
12
|
import { useParams } from 'react-router-dom'
|
|
18
13
|
import { apiFetch } from '@core/lib/api'
|
|
@@ -37,48 +32,54 @@ import {
|
|
|
37
32
|
|
|
38
33
|
|
|
39
34
|
import { PageInstructions } from '../../../components/admin/PageInstructions'
|
|
40
|
-
|
|
41
|
-
// CIL[
|
|
42
|
-
// CIL[DOC-
|
|
43
|
-
// CIL[DOC-
|
|
44
|
-
// CIL[DOC-
|
|
45
|
-
// CIL[DOC-CONTRACT inputs="none" outputs="Message type contract" errors="none" side_effects="none"]
|
|
46
|
-
// CIL[DOC-MICRO logic_summary="Describes id, role, content, optional sources, tool_calls_made, and loading flag" notable_decisions="[]"]
|
|
47
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
48
|
-
// CIL[DOC-STABILITY stability="stable"]
|
|
49
|
-
// CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: .framework/functions/_shared/principal.ts, .framework/migrations/025_retype_threads_messages.sql, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/src/pages/admin/IntegrationsPage.tsx, .framework/functions/_shared/schema-utils.ts, \."]
|
|
50
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
51
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
52
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
35
|
+
|
|
36
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Chat interface for the CIL agent that answers natural-language questions about indexed code'; No verified external callers; imports: .framework/src/lib/api.ts,.framework/src/components/ui/button.tsx,.framework/src/components/ui/textarea.tsx"]
|
|
37
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
38
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
39
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
53
40
|
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
54
41
|
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
42
|
+
// CIL[END stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:module_header:module_header"]
|
|
43
|
+
// CIL[BEGIN stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:Message:interface" type="interface" identity="Message" parent="~/.framework/src/pages/admin/cil/CILAgentPage.tsx"]
|
|
44
|
+
// CIL[DOC-MACRO purpose="Message shape for CIL agent chat exchanges"]
|
|
45
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Describe the fields for a chat message including role, content, optional sources and tool calls"]
|
|
46
|
+
// CIL[DOC-CONTEXT module=".framework/src/pages/admin/cil" layer="admin-ui" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/badge.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/components/ui/textarea.tsx,.framework/src/lib/api.ts,.framework/src/pages/admin/cil/CILAgentPage.tsx"]
|
|
47
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="TypeScript interface" errors="none" side_effects="none"]
|
|
48
|
+
// CIL[DOC-MICRO logic_summary="Defines id, role, content, sources, tool_calls_made, and loading fields." notable_decisions="[]"]
|
|
49
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
50
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
51
|
+
|
|
55
52
|
interface Message {
|
|
56
53
|
id: string
|
|
57
54
|
role: 'user' | 'assistant' | 'system'
|
|
58
55
|
content: string
|
|
59
|
-
|
|
56
|
+
message_type?: string
|
|
57
|
+
tool?: string
|
|
58
|
+
sources?: { id: string; label: string }[]
|
|
60
59
|
tool_calls_made?: string[]
|
|
61
60
|
loading?: boolean
|
|
62
61
|
}
|
|
62
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Message shape for CIL agent chat exchanges'; No verified external callers; imports: .framework/src/lib/api.ts,.framework/src/components/ui/button.tsx,.framework/src/components/ui/textarea.tsx"]
|
|
63
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
64
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
65
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
66
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
67
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
68
|
+
// CIL[END stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:Message:interface"]
|
|
63
69
|
|
|
64
70
|
|
|
65
71
|
|
|
66
72
|
|
|
67
|
-
|
|
68
|
-
// CIL[BEGIN
|
|
69
|
-
// CIL[DOC-MACRO purpose="
|
|
70
|
-
// CIL[DOC-RESPONSIBILITY responsibility="
|
|
71
|
-
// CIL[DOC-CONTEXT module="
|
|
72
|
-
// CIL[DOC-CONTRACT inputs="
|
|
73
|
-
// CIL[DOC-MICRO logic_summary="Splits on
|
|
74
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.
|
|
73
|
+
|
|
74
|
+
// CIL[BEGIN stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:renderMarkdown:function" type="function" identity="renderMarkdown" parent="~/.framework/src/pages/admin/cil/CILAgentPage.tsx"]
|
|
75
|
+
// CIL[DOC-MACRO purpose="Convert assistant answer text with markdown-like code and emphasis markers into React nodes"]
|
|
76
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Render inline code, bold text, code blocks, and line breaks safely for assistant messages"]
|
|
77
|
+
// CIL[DOC-CONTEXT module=".framework/src/pages/admin/cil" layer="admin-ui" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/badge.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/components/ui/textarea.tsx,.framework/src/lib/api.ts,.framework/src/pages/admin/cil/CILAgentPage.tsx"]
|
|
78
|
+
// CIL[DOC-CONTRACT inputs="text: string" outputs="Array of React nodes" errors="none" side_effects="none"]
|
|
79
|
+
// CIL[DOC-MICRO logic_summary="Splits text on code fences, then parses inline markers for code and bold." notable_decisions="[]"]
|
|
80
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
75
81
|
// CIL[DOC-STABILITY stability="stable"]
|
|
76
|
-
|
|
77
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
78
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
79
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
80
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
81
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
82
|
+
|
|
82
83
|
function renderMarkdown(text: string): React.ReactNode[] {
|
|
83
84
|
const parts: React.ReactNode[] = []
|
|
84
85
|
let key = 0
|
|
@@ -98,45 +99,54 @@ function renderMarkdown(text: string): React.ReactNode[] {
|
|
|
98
99
|
)
|
|
99
100
|
} else {
|
|
100
101
|
|
|
102
|
+
|
|
103
|
+
|
|
101
104
|
const inline = seg.split(/(`[^`]+`|\*\*[^*]+\*\*|\n)/g).map((chunk, i) => {
|
|
102
105
|
if (chunk.startsWith('`') && chunk.endsWith('`')) {
|
|
103
106
|
return <code key={i} className="bg-muted px-1 py-0.5 rounded text-xs font-mono">{chunk.slice(1, -1)}</code>
|
|
104
107
|
}
|
|
108
|
+
|
|
105
109
|
if (chunk.startsWith('**') && chunk.endsWith('**')) {
|
|
106
110
|
return <strong key={i}>{chunk.slice(2, -2)}</strong>
|
|
107
111
|
}
|
|
108
112
|
if (chunk === '\n') return <br key={i} />
|
|
109
113
|
return chunk
|
|
110
114
|
})
|
|
115
|
+
|
|
111
116
|
parts.push(<span key={key++}>{inline}</span>)
|
|
112
117
|
}
|
|
118
|
+
|
|
113
119
|
}
|
|
114
120
|
return parts
|
|
115
121
|
}
|
|
116
122
|
|
|
123
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Convert assistant answer text with markdown-like code and emphasis markers into React nodes'; No verified external callers; imports: .framework/src/lib/api.ts,.framework/src/components/ui/button.tsx,.framework/src/components/ui/textarea.tsx"]
|
|
124
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
125
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
126
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
127
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
128
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
129
|
+
// CIL[END stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:renderMarkdown:function"]
|
|
130
|
+
|
|
117
131
|
|
|
118
132
|
|
|
119
|
-
|
|
120
|
-
// CIL[BEGIN
|
|
121
|
-
// CIL[DOC-MACRO purpose="
|
|
122
|
-
// CIL[DOC-RESPONSIBILITY responsibility="
|
|
123
|
-
// CIL[DOC-CONTEXT module="
|
|
124
|
-
// CIL[DOC-CONTRACT inputs="
|
|
125
|
-
// CIL[DOC-MICRO logic_summary="
|
|
126
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.
|
|
133
|
+
|
|
134
|
+
// CIL[BEGIN stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:MessageBubble:component" type="component" identity="MessageBubble" parent="~/.framework/src/pages/admin/cil/CILAgentPage.tsx"]
|
|
135
|
+
// CIL[DOC-MACRO purpose="Display a single chat message with avatar, markdown body, and optional tool and source chips"]
|
|
136
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Render user or assistant message and link source chunks to the chunk detail page"]
|
|
137
|
+
// CIL[DOC-CONTEXT module=".framework/src/pages/admin/cil" layer="admin-ui" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/badge.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/components/ui/textarea.tsx,.framework/src/lib/api.ts,.framework/src/pages/admin/cil/CILAgentPage.tsx"]
|
|
138
|
+
// CIL[DOC-CONTRACT inputs="message, projectId, appPath" outputs="JSX message row" errors="none" side_effects="none"]
|
|
139
|
+
// CIL[DOC-MICRO logic_summary="Chooses avatar icon, renders markdown for assistant, and shows tool calls and source chips." notable_decisions="[]"]
|
|
140
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
127
141
|
// CIL[DOC-STABILITY stability="stable"]
|
|
128
|
-
|
|
129
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
130
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
131
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
132
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
133
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
142
|
+
|
|
134
143
|
function MessageBubble({ message, projectId, appPath }: {
|
|
135
144
|
message: Message
|
|
136
145
|
projectId: string
|
|
137
146
|
appPath: (p: string) => string
|
|
138
147
|
}) {
|
|
139
148
|
const isUser = message.role === 'user'
|
|
149
|
+
const mt = message.message_type
|
|
140
150
|
|
|
141
151
|
if (message.loading) {
|
|
142
152
|
return (
|
|
@@ -153,6 +163,39 @@ function MessageBubble({ message, projectId, appPath }: {
|
|
|
153
163
|
)
|
|
154
164
|
}
|
|
155
165
|
|
|
166
|
+
// Intermediate research steps render as a compact left-aligned trail rather
|
|
167
|
+
// than full chat bubbles so the plan/tool activity is visually distinct from
|
|
168
|
+
// the agent's actual replies.
|
|
169
|
+
if (!isUser && (mt === 'plan' || mt === 'thinking' || mt === 'tool_call' || mt === 'tool_result')) {
|
|
170
|
+
return (
|
|
171
|
+
<div className="flex items-start gap-2.5 pl-8">
|
|
172
|
+
<div className="flex-1 min-w-0 text-xs">
|
|
173
|
+
{mt === 'tool_call' && (
|
|
174
|
+
<span className="inline-flex items-center gap-1.5 bg-amber-50 border border-amber-200 text-amber-700 rounded-full px-2.5 py-1">
|
|
175
|
+
<Wrench className="h-3 w-3" /> {message.tool || 'tool'} — running
|
|
176
|
+
</span>
|
|
177
|
+
)}
|
|
178
|
+
{mt === 'tool_result' && (
|
|
179
|
+
<span className="inline-flex items-center gap-1.5 bg-emerald-50 border border-emerald-200 text-emerald-700 rounded-full px-2.5 py-1">
|
|
180
|
+
<Wrench className="h-3 w-3" /> {message.tool || 'tool'} — done
|
|
181
|
+
</span>
|
|
182
|
+
)}
|
|
183
|
+
{(mt === 'plan' || mt === 'thinking') && (
|
|
184
|
+
<div className="text-muted-foreground italic border-l-2 border-indigo-200 pl-3 py-0.5">
|
|
185
|
+
<span className="text-[10px] uppercase tracking-wide text-indigo-400 not-italic font-medium mr-1.5">
|
|
186
|
+
{mt === 'plan' ? 'plan' : 'thinking'}
|
|
187
|
+
</span>
|
|
188
|
+
{renderMarkdown(message.content)}
|
|
189
|
+
</div>
|
|
190
|
+
)}
|
|
191
|
+
</div>
|
|
192
|
+
</div>
|
|
193
|
+
)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const isAwaiting = mt === 'awaiting_input'
|
|
197
|
+
const isError = mt === 'error'
|
|
198
|
+
|
|
156
199
|
return (
|
|
157
200
|
<div className={`flex items-start gap-2.5 ${isUser ? 'flex-row-reverse' : ''}`}>
|
|
158
201
|
<div className={`h-6 w-6 rounded-full flex items-center justify-center shrink-0 mt-0.5 ${isUser ? 'bg-slate-200' : 'bg-indigo-100'}`}>
|
|
@@ -160,14 +203,22 @@ function MessageBubble({ message, projectId, appPath }: {
|
|
|
160
203
|
? <User className="h-3.5 w-3.5 text-slate-600" />
|
|
161
204
|
: <Bot className="h-3.5 w-3.5 text-indigo-600" />
|
|
162
205
|
}
|
|
206
|
+
|
|
163
207
|
</div>
|
|
164
208
|
|
|
165
209
|
<div className={`flex-1 min-w-0 ${isUser ? 'items-end' : 'items-start'} flex flex-col`}>
|
|
166
210
|
<div className={`rounded-xl px-3.5 py-2.5 max-w-[85%] text-sm leading-relaxed ${
|
|
167
211
|
isUser
|
|
168
212
|
? 'bg-slate-900 text-white rounded-tr-sm'
|
|
169
|
-
:
|
|
213
|
+
: isError
|
|
214
|
+
? 'bg-red-50 border border-red-200 text-red-700 rounded-tl-sm'
|
|
215
|
+
: isAwaiting
|
|
216
|
+
? 'bg-indigo-50 border border-indigo-200 rounded-tl-sm'
|
|
217
|
+
: 'bg-muted rounded-tl-sm'
|
|
170
218
|
}`}>
|
|
219
|
+
{isAwaiting && (
|
|
220
|
+
<div className="text-[10px] uppercase tracking-wide text-indigo-500 font-medium mb-1">Needs your input</div>
|
|
221
|
+
)}
|
|
171
222
|
{isUser
|
|
172
223
|
? <span className="whitespace-pre-wrap">{message.content}</span>
|
|
173
224
|
: <div className="prose-sm">{renderMarkdown(message.content)}</div>
|
|
@@ -184,12 +235,12 @@ function MessageBubble({ message, projectId, appPath }: {
|
|
|
184
235
|
))}
|
|
185
236
|
{(message.sources || []).map((src, i) => (
|
|
186
237
|
<a
|
|
187
|
-
key={`src-${src}-${i}`}
|
|
188
|
-
href={appPath(projectId ? `/cil/${projectId}/chunks/${src}` : `/cil/chunks/${src}`)}
|
|
238
|
+
key={`src-${src.id}-${i}`}
|
|
239
|
+
href={appPath(projectId ? `/cil/${projectId}/chunks/${src.id}` : `/cil/chunks/${src.id}`)}
|
|
189
240
|
className="inline-flex items-center gap-1 text-xs bg-indigo-50 border border-indigo-200 text-indigo-700 rounded-full px-2 py-0.5 hover:bg-indigo-100 transition-colors"
|
|
190
|
-
title={`Open chunk: ${src}`}
|
|
241
|
+
title={`Open chunk: ${src.label}`}
|
|
191
242
|
>
|
|
192
|
-
<Code2 className="h-2.5 w-2.5" /> {src}
|
|
243
|
+
<Code2 className="h-2.5 w-2.5" /> {src.label}
|
|
193
244
|
</a>
|
|
194
245
|
))}
|
|
195
246
|
</div>
|
|
@@ -199,23 +250,25 @@ function MessageBubble({ message, projectId, appPath }: {
|
|
|
199
250
|
)
|
|
200
251
|
}
|
|
201
252
|
|
|
253
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Display a single chat message with avatar, markdown body, and optional tool and source chips'; No verified external callers; imports: .framework/src/lib/api.ts,.framework/src/components/ui/button.tsx,.framework/src/components/ui/textarea.tsx"]
|
|
254
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
255
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
256
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
257
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
258
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
259
|
+
// CIL[END stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:MessageBubble:component"]
|
|
202
260
|
|
|
203
261
|
|
|
204
|
-
|
|
205
|
-
// CIL[BEGIN
|
|
206
|
-
// CIL[DOC-MACRO purpose="
|
|
207
|
-
// CIL[DOC-RESPONSIBILITY responsibility="
|
|
208
|
-
// CIL[DOC-CONTEXT module="
|
|
209
|
-
// CIL[DOC-CONTRACT inputs="none" outputs="
|
|
210
|
-
// CIL[DOC-MICRO logic_summary="
|
|
211
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.
|
|
262
|
+
|
|
263
|
+
// CIL[BEGIN stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:SUGGESTIONS:constant" type="constant" identity="SUGGESTIONS" parent="~/.framework/src/pages/admin/cil/CILAgentPage.tsx"]
|
|
264
|
+
// CIL[DOC-MACRO purpose="Preset example prompts for the CIL agent chat"]
|
|
265
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Provide ready-made questions users can click to start a conversation"]
|
|
266
|
+
// CIL[DOC-CONTEXT module=".framework/src/pages/admin/cil" layer="admin-ui" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/badge.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/components/ui/textarea.tsx,.framework/src/lib/api.ts,.framework/src/pages/admin/cil/CILAgentPage.tsx"]
|
|
267
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="Array of prompt strings" errors="none" side_effects="none"]
|
|
268
|
+
// CIL[DOC-MICRO logic_summary="Static list of questions covering authentication, embeddings, refactor safety, side effects, and undocumented chunks." notable_decisions="[]"]
|
|
269
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
212
270
|
// CIL[DOC-STABILITY stability="stable"]
|
|
213
|
-
|
|
214
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
215
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
216
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
217
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
218
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
271
|
+
|
|
219
272
|
const SUGGESTIONS = [
|
|
220
273
|
'What does the authentication middleware do?',
|
|
221
274
|
'Which functions write to the embeddings table?',
|
|
@@ -225,23 +278,57 @@ const SUGGESTIONS = [
|
|
|
225
278
|
'Show me undocumented chunks in this project',
|
|
226
279
|
]
|
|
227
280
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
// CIL[
|
|
231
|
-
// CIL[
|
|
232
|
-
// CIL[DOC-MACRO purpose="Render the interactive CIL agent chat page"]
|
|
233
|
-
// CIL[DOC-RESPONSIBILITY responsibility="Manage chat state, send questions to the CIL agent API, and render the conversation UI"]
|
|
234
|
-
// CIL[DOC-CONTEXT module="cortex:cil-agent" layer="presentation" related_files="[]"]
|
|
235
|
-
// CIL[DOC-CONTRACT inputs="none" outputs="JSX.Element" errors="Displays API errors as assistant messages" side_effects="Calls /api/cil-agent and /api/cil-project; updates messages and input state"]
|
|
236
|
-
// CIL[DOC-MICRO logic_summary="Loads project title, maintains messages/input/sending refs, sends messages via apiFetch, scrolls to bottom, and renders messages and input area" notable_decisions="[]"]
|
|
237
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
238
|
-
// CIL[DOC-STABILITY stability="stable"]
|
|
239
|
-
// CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
240
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
241
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
242
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
281
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Preset example prompts for the CIL agent chat'; No verified external callers; imports: .framework/src/lib/api.ts,.framework/src/components/ui/button.tsx,.framework/src/components/ui/textarea.tsx"]
|
|
282
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
283
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
284
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
243
285
|
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
244
286
|
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
287
|
+
// CIL[END stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:SUGGESTIONS:constant"]
|
|
288
|
+
|
|
289
|
+
// CIL[BEGIN stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:mapRecordToMessage:function" type="function" identity="mapRecordToMessage" parent="~/.framework/src/pages/admin/cil/CILAgentPage.tsx"]
|
|
290
|
+
// CIL[DOC-MACRO purpose="Map a persisted thread message record into the chat display Message shape"]
|
|
291
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Translate message_type, tool, and retrieved_sources fields from a messages row into a renderable Message"]
|
|
292
|
+
// CIL[DOC-CONTEXT module=".framework/src/pages/admin/cil" layer="admin-ui" related_files=".framework/src/pages/admin/cil/CILAgentPage.tsx"]
|
|
293
|
+
// CIL[DOC-CONTRACT inputs="rec: messages record" outputs="Message" errors="none" side_effects="none"]
|
|
294
|
+
// CIL[DOC-MICRO logic_summary="Derives role from message_type, sources from retrieved_sources, and surfaces tool name for tool_call/tool_result rows." notable_decisions="[]"]
|
|
295
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
296
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
297
|
+
function mapRecordToMessage(rec: any): Message {
|
|
298
|
+
const mt = rec?.data?.message_type || 'agent'
|
|
299
|
+
const role: Message['role'] = mt === 'human' ? 'user' : (mt === 'system' ? 'system' : 'assistant')
|
|
300
|
+
const rawSources = Array.isArray(rec?.data?.cited_sources) && rec.data.cited_sources.length
|
|
301
|
+
? rec.data.cited_sources
|
|
302
|
+
: (rec?.data?.retrieved_sources || [])
|
|
303
|
+
const sources = rawSources
|
|
304
|
+
.map((s: any) => ({ id: s.document_id, label: s.chunk_name || s.title || s.document_id }))
|
|
305
|
+
.filter((s: any) => s.id)
|
|
306
|
+
return {
|
|
307
|
+
id: rec.id,
|
|
308
|
+
role,
|
|
309
|
+
content: rec.content || '',
|
|
310
|
+
message_type: mt,
|
|
311
|
+
tool: rec?.data?.tool,
|
|
312
|
+
sources,
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Map a persisted thread message record into the chat display Message shape'; imports: none"]
|
|
316
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Local impact only; used by CILAgentPage.loadMessages"]
|
|
317
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
318
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
319
|
+
// CIL[END stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:mapRecordToMessage:function"]
|
|
320
|
+
|
|
321
|
+
const TERMINAL_STATUSES = ['complete', 'awaiting_input', 'failed']
|
|
322
|
+
const MAX_STEPS = 20
|
|
323
|
+
|
|
324
|
+
// CIL[BEGIN stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:CILAgentPage:component" type="component" identity="CILAgentPage" parent="~/.framework/src/pages/admin/cil/CILAgentPage.tsx"]
|
|
325
|
+
// CIL[DOC-MACRO purpose="Main admin page for the CIL agent chat"]
|
|
326
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Manage chat state, call the CIL agent API, render messages, suggestions, and input"]
|
|
327
|
+
// CIL[DOC-CONTEXT module=".framework/src/pages/admin/cil" layer="admin-ui" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/badge.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/components/ui/textarea.tsx,.framework/src/lib/api.ts,.framework/src/pages/admin/cil/CILAgentPage.tsx"]
|
|
328
|
+
// CIL[DOC-CONTRACT inputs="project_id from URL and user typed question" outputs="Rendered chat UI with message history and source links" errors="API request failures render error message in chat" side_effects="Calls /api/cil-agent?action=prepare, /api/ai-agents?action=run, /api/admin-data?entity=messages, and /api/cil-project"]
|
|
329
|
+
// CIL[DOC-MICRO logic_summary="Fetches project title, scrolls to new messages, sends question to API, and renders conversation with suggestions." notable_decisions="[]"]
|
|
330
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
331
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
245
332
|
export default function CILAgentPage() {
|
|
246
333
|
const { id: projectId } = useParams<{ id: string }>()
|
|
247
334
|
const appPath = (path: string) => '/spine-framework/admin' + (path.startsWith('/') ? path : '/' + path)
|
|
@@ -249,6 +336,12 @@ export default function CILAgentPage() {
|
|
|
249
336
|
const [input, setInput] = useState('')
|
|
250
337
|
const [sending, setSending] = useState(false)
|
|
251
338
|
const [projectTitle, setProjectTitle] = useState('')
|
|
339
|
+
const [threadId, setThreadId] = useState<string | null>(null)
|
|
340
|
+
const conversationIdRef = useRef<string | null>(
|
|
341
|
+
(typeof localStorage !== 'undefined' && projectId)
|
|
342
|
+
? localStorage.getItem(`cil-agent-conversation:${projectId}`)
|
|
343
|
+
: null
|
|
344
|
+
)
|
|
252
345
|
const bottomRef = useRef<HTMLDivElement>(null)
|
|
253
346
|
const textareaRef = useRef<HTMLTextAreaElement>(null)
|
|
254
347
|
|
|
@@ -269,54 +362,80 @@ export default function CILAgentPage() {
|
|
|
269
362
|
bottomRef.current?.scrollIntoView({ behavior: 'smooth' })
|
|
270
363
|
}, [messages])
|
|
271
364
|
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
const
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
365
|
+
const loadMessages = useCallback(async (tid: string) => {
|
|
366
|
+
const res = await apiFetch(`/api/admin-data?action=list&entity=messages&thread_id=${tid}&sort_field=created_at&sort_direction=asc&limit=200`)
|
|
367
|
+
const json = await res.json()
|
|
368
|
+
const recs = Array.isArray(json?.data) ? json.data : (Array.isArray(json) ? json : [])
|
|
369
|
+
setMessages(recs.map(mapRecordToMessage))
|
|
370
|
+
}, [])
|
|
371
|
+
|
|
372
|
+
const ensureThread = useCallback(async (): Promise<string> => {
|
|
373
|
+
if (!conversationIdRef.current) {
|
|
374
|
+
conversationIdRef.current = crypto.randomUUID()
|
|
375
|
+
if (projectId && typeof localStorage !== 'undefined') {
|
|
376
|
+
localStorage.setItem(`cil-agent-conversation:${projectId}`, conversationIdRef.current)
|
|
377
|
+
}
|
|
285
378
|
}
|
|
379
|
+
const prep = await apiFetch('/api/cil-agent?action=prepare', {
|
|
380
|
+
method: 'POST',
|
|
381
|
+
headers: { 'Content-Type': 'application/json' },
|
|
382
|
+
body: JSON.stringify({
|
|
383
|
+
project_id: projectId,
|
|
384
|
+
conversation_id: conversationIdRef.current,
|
|
385
|
+
}),
|
|
386
|
+
}).then(r => r.json())
|
|
387
|
+
const tid = prep?.thread_id || prep?.data?.thread_id
|
|
388
|
+
if (!tid) throw new Error('Failed to prepare CIL agent thread')
|
|
389
|
+
setThreadId(tid)
|
|
390
|
+
return tid
|
|
391
|
+
}, [projectId])
|
|
286
392
|
|
|
287
|
-
|
|
393
|
+
// Restore an existing conversation thread + history only when a persisted
|
|
394
|
+
// conversation_id already exists — a brand-new session stays lazy until the
|
|
395
|
+
// first message so we don't create empty threads.
|
|
396
|
+
useEffect(() => {
|
|
397
|
+
if (!projectId || threadId || !conversationIdRef.current) return
|
|
398
|
+
let cancelled = false
|
|
399
|
+
ensureThread()
|
|
400
|
+
.then(tid => { if (!cancelled) return loadMessages(tid) })
|
|
401
|
+
.catch(() => {})
|
|
402
|
+
return () => { cancelled = true }
|
|
403
|
+
}, [projectId, threadId, ensureThread, loadMessages])
|
|
404
|
+
|
|
405
|
+
const sendMessage = useCallback(async (text: string) => {
|
|
406
|
+
const trimmed = text.trim()
|
|
407
|
+
if (!trimmed || sending) return
|
|
408
|
+
|
|
409
|
+
setMessages(prev => [
|
|
410
|
+
...prev,
|
|
411
|
+
{ id: crypto.randomUUID(), role: 'user', content: trimmed },
|
|
412
|
+
{ id: crypto.randomUUID(), role: 'assistant', content: '', loading: true },
|
|
413
|
+
])
|
|
288
414
|
setInput('')
|
|
289
415
|
setSending(true)
|
|
290
416
|
|
|
291
417
|
try {
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
{
|
|
307
|
-
id: crypto.randomUUID(),
|
|
308
|
-
role: 'assistant',
|
|
309
|
-
content: answer,
|
|
310
|
-
sources: r?.sources || [],
|
|
311
|
-
tool_calls_made: r?.tool_calls_made || [],
|
|
312
|
-
},
|
|
313
|
-
])
|
|
418
|
+
const tid = threadId || (await ensureThread())
|
|
419
|
+
|
|
420
|
+
let userMessage: string = trimmed
|
|
421
|
+
for (let i = 0; i < MAX_STEPS; i++) {
|
|
422
|
+
const res = await apiFetch('/api/ai-agents?action=run', {
|
|
423
|
+
method: 'POST',
|
|
424
|
+
headers: { 'Content-Type': 'application/json' },
|
|
425
|
+
body: JSON.stringify({ thread_id: tid, user_message: userMessage, mode: 'step' }),
|
|
426
|
+
}).then(r => r.json())
|
|
427
|
+
userMessage = ''
|
|
428
|
+
await loadMessages(tid)
|
|
429
|
+
const status = res?.status || res?.data?.status
|
|
430
|
+
if (TERMINAL_STATUSES.includes(status)) break
|
|
431
|
+
}
|
|
314
432
|
} catch (err) {
|
|
315
433
|
setMessages(prev => [
|
|
316
|
-
...prev.
|
|
434
|
+
...prev.filter(m => !m.loading),
|
|
317
435
|
{
|
|
318
436
|
id: crypto.randomUUID(),
|
|
319
437
|
role: 'assistant',
|
|
438
|
+
message_type: 'error',
|
|
320
439
|
content: `Error: ${err instanceof Error ? err.message : String(err)}`,
|
|
321
440
|
},
|
|
322
441
|
])
|
|
@@ -324,7 +443,7 @@ export default function CILAgentPage() {
|
|
|
324
443
|
setSending(false)
|
|
325
444
|
setTimeout(() => textareaRef.current?.focus(), 50)
|
|
326
445
|
}
|
|
327
|
-
}, [projectId, sending])
|
|
446
|
+
}, [projectId, sending, threadId, ensureThread, loadMessages])
|
|
328
447
|
|
|
329
448
|
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
|
330
449
|
if (e.key === 'Enter' && !e.shiftKey) {
|
|
@@ -334,6 +453,11 @@ export default function CILAgentPage() {
|
|
|
334
453
|
}
|
|
335
454
|
|
|
336
455
|
const clearConversation = () => {
|
|
456
|
+
conversationIdRef.current = null
|
|
457
|
+
if (projectId && typeof localStorage !== 'undefined') {
|
|
458
|
+
localStorage.removeItem(`cil-agent-conversation:${projectId}`)
|
|
459
|
+
}
|
|
460
|
+
setThreadId(null)
|
|
337
461
|
setMessages([])
|
|
338
462
|
setInput('')
|
|
339
463
|
textareaRef.current?.focus()
|
|
@@ -462,4 +586,10 @@ export default function CILAgentPage() {
|
|
|
462
586
|
)
|
|
463
587
|
}
|
|
464
588
|
|
|
465
|
-
// CIL[
|
|
589
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Main admin page for the CIL agent chat'; No verified external callers; imports: .framework/src/lib/api.ts,.framework/src/components/ui/button.tsx,.framework/src/components/ui/textarea.tsx"]
|
|
590
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
591
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
592
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
593
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
594
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
595
|
+
// CIL[END stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:CILAgentPage:component"]
|