spine-framework 0.3.124 → 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 +179 -69
- package/.framework/cli/commands/generate.ts +83 -143
- 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} +158 -56
- package/.framework/functions/_shared/db.ts +80 -126
- package/.framework/functions/_shared/hash-api-key.ts +63 -0
- package/.framework/functions/_shared/index.ts +224 -335
- 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 +188 -16
- 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 +685 -537
- 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 +187 -144
- 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 +195 -116
- 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 +5 -2
- 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,1227 @@
|
|
|
1
|
+
|
|
2
|
+
const MAP_SOURCE_STATUS: Record<'first' | 'second', { prior: string; target: string }> = {
|
|
3
|
+
first: { prior: '6-embedded', target: '7-mapped' },
|
|
4
|
+
second: { prior: '9-embedded', target: '10-mapped' },
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function getMapSourceFilePaths(projectItem: any, secondPass: boolean): string[] {
|
|
8
|
+
const fileStatuses: Record<string, string> = projectItem?.data?.file_statuses || {}
|
|
9
|
+
const { prior } = secondPass ? MAP_SOURCE_STATUS.second : MAP_SOURCE_STATUS.first
|
|
10
|
+
return Object.entries(fileStatuses)
|
|
11
|
+
.filter(([, status]) => status === prior)
|
|
12
|
+
.map(([filePath]) => filePath)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_module_header_1784235266" type="module_header" identity="module_header" parent="none"]
|
|
16
|
+
// CIL[DOC-MACRO purpose="Module header and top-level exports for cortex.functions.custom_cil-callmap"]
|
|
17
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Own module-level imports, exports, and configuration for cortex.functions.custom_cil-callmap"]
|
|
18
|
+
// CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[\".framework/migrations/015_simplify_apps_table.sql\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"custom/apps/portal/pages/ContentPage.tsx\",\".framework/src/components/ui/table-primitives.tsx\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"\\\"]"]
|
|
19
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="module exports and side effects" errors="none" side_effects="none"]
|
|
20
|
+
// CIL[DOC-MICRO logic_summary="Declares module scope, imports dependencies, and exports public surface of cortex.functions.custom_cil-callmap" notable_decisions="[]"]
|
|
21
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
22
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
23
|
+
// CIL[DOC-AUDIENCE audience="developer"]
|
|
24
|
+
// CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: .framework/migrations/015_simplify_apps_table.sql, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, custom/apps/portal/pages/ContentPage.tsx, .framework/src/components/ui/table-primitives.tsx, .framework/src/pages/admin/TypeDetailPage.tsx, \."]
|
|
25
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
26
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
27
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
28
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
29
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
import { createHandler } from './_shared/middleware'
|
|
36
|
+
import { adminDb } from './_shared/db'
|
|
37
|
+
import { resolveLinkTypeId } from './_shared/resolve-ids'
|
|
38
|
+
import { create as adminCreate, update as adminUpdate } from './admin-data'
|
|
39
|
+
import { FileStatus, FileTreeNode, isSelectedPath, getFileStatus, updateTreeNodeStatus, saveProjectTree } from './_shared/cil'
|
|
40
|
+
import * as fs from 'fs'
|
|
41
|
+
import * as path from 'path'
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
// CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_module_header_1784235266"]
|
|
52
|
+
// CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_status_rank_1784235266" type="variable" identity="status_rank" parent="none"]
|
|
53
|
+
// CIL[DOC-MACRO purpose="Defines status_rank configuration or state in cortex.functions.custom_cil-callmap"]
|
|
54
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Hold the value and default configuration for status_rank"]
|
|
55
|
+
// CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[\".framework/src/pages/admin/TypeDetailPage.tsx\",\".framework/functions/_shared/principal.ts\",\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\"custom/apps/portal/pages/ContentPage.tsx\",\"\\\"]"]
|
|
56
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="value of status_rank" errors="none" side_effects="none"]
|
|
57
|
+
// CIL[DOC-MICRO logic_summary="Declares status_rank with initial value or constant binding used by cortex.functions.custom_cil-callmap" notable_decisions="[]"]
|
|
58
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
59
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
60
|
+
// CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: .framework/src/pages/admin/TypeDetailPage.tsx, .framework/functions/_shared/principal.ts, custom/apps/cortex/functions/custom_cil-embeddings.ts, .framework/src/pages/admin/IntegrationsPage.tsx, custom/apps/portal/pages/ContentPage.tsx, \."]
|
|
61
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
62
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
63
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
64
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
65
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
66
|
+
const STATUS_RANK: Record<string, number> = {
|
|
67
|
+
'2-discovered': 2,
|
|
68
|
+
'3-selected': 3,
|
|
69
|
+
'4-chunked': 4,
|
|
70
|
+
'5-documented': 5,
|
|
71
|
+
'6-embedded': 6,
|
|
72
|
+
'7-mapped': 7,
|
|
73
|
+
'8-enriched': 8,
|
|
74
|
+
'9-embedded': 9,
|
|
75
|
+
'10-mapped': 10,
|
|
76
|
+
|
|
77
|
+
'pass2_complete': 4,
|
|
78
|
+
'pass3_complete': 5,
|
|
79
|
+
'pass4_complete': 6,
|
|
80
|
+
'pass4b_complete': 7,
|
|
81
|
+
'pass6_complete': 8,
|
|
82
|
+
'pass7_complete': 9,
|
|
83
|
+
'pass8_complete': 10,
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Keep REST URL length under the ~8k character limit for UUID IN clauses.
|
|
87
|
+
const UUID_IN_LIMIT = 100
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
// CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_status_rank_1784235266"]
|
|
95
|
+
// CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_rank_1784235266" type="function" identity="rank" parent="none"]
|
|
96
|
+
// CIL[DOC-MACRO purpose="Implements rank logic in cortex.functions.custom_cil-callmap"]
|
|
97
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Execute rank and return its computed result"]
|
|
98
|
+
// CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\".framework/functions/_shared/principal.ts\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\".framework/migrations/015_simplify_apps_table.sql\",\"\\\"]"]
|
|
99
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="return value from function execution" errors="throws on invalid input or runtime failure" side_effects="none"]
|
|
100
|
+
// CIL[DOC-MICRO logic_summary="Provides rank with rank(status: string | undefined inputs, handling internal flow and returning a result" notable_decisions="[]"]
|
|
101
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
102
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
103
|
+
// CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 2. Direct calls: 0. Related files: custom/apps/cortex/functions/custom_cil-embeddings.ts, .framework/functions/_shared/principal.ts, .framework/src/pages/admin/TypeDetailPage.tsx, .framework/src/pages/admin/IntegrationsPage.tsx, .framework/migrations/015_simplify_apps_table.sql, \."]
|
|
104
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 2. Total affected: 2."]
|
|
105
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
106
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
107
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
108
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
109
|
+
function rank(status: string | undefined): number {
|
|
110
|
+
return status ? STATUS_RANK[status] || 0 : 0
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
// CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_rank_1784235266"]
|
|
122
|
+
// CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractedimport_1784235266" type="interface" identity="extractedimport" parent="none"]
|
|
123
|
+
// CIL[DOC-MACRO purpose="Defines the extractedimport type contract in cortex.functions.custom_cil-callmap"]
|
|
124
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Describe the shape and allowed fields for extractedimport"]
|
|
125
|
+
// CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[\".framework/src/pages/admin/TypeDetailPage.tsx\",\".framework/functions/_shared/principal.ts\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\".framework/migrations/015_simplify_apps_table.sql\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"\\\"]"]
|
|
126
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="type definition for extractedimport" errors="none" side_effects="none"]
|
|
127
|
+
// CIL[DOC-MICRO logic_summary="Declares TypeScript type/interface extractedimport with member definitions" notable_decisions="[]"]
|
|
128
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
129
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
130
|
+
// CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: .framework/src/pages/admin/TypeDetailPage.tsx, .framework/functions/_shared/principal.ts, .framework/src/pages/admin/IntegrationsPage.tsx, .framework/migrations/015_simplify_apps_table.sql, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, \."]
|
|
131
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
132
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
133
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
134
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
135
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
136
|
+
interface ExtractedImport {
|
|
137
|
+
from_path: string
|
|
138
|
+
symbols: string[]
|
|
139
|
+
is_default: boolean
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
// CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractedimport_1784235266"]
|
|
149
|
+
// CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractedcall_1784235266" type="interface" identity="extractedcall" parent="none"]
|
|
150
|
+
// CIL[DOC-MACRO purpose="Defines the extractedcall type contract in cortex.functions.custom_cil-callmap"]
|
|
151
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Describe the shape and allowed fields for extractedcall"]
|
|
152
|
+
// CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[\".framework/src/pages/admin/TypeDetailPage.tsx\",\".framework/functions/_shared/principal.ts\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\".framework/migrations/015_simplify_apps_table.sql\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"\\\"]"]
|
|
153
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="type definition for extractedcall" errors="none" side_effects="none"]
|
|
154
|
+
// CIL[DOC-MICRO logic_summary="Declares TypeScript type/interface extractedcall with member definitions" notable_decisions="[]"]
|
|
155
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
156
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
157
|
+
// CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: .framework/src/pages/admin/TypeDetailPage.tsx, .framework/functions/_shared/principal.ts, .framework/src/pages/admin/IntegrationsPage.tsx, .framework/migrations/015_simplify_apps_table.sql, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, \."]
|
|
158
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
159
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
160
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
161
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
162
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
163
|
+
interface ExtractedCall {
|
|
164
|
+
callee_name: string
|
|
165
|
+
is_await: boolean
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
// CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractedcall_1784235266"]
|
|
178
|
+
// CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractimports_1784235266" type="function" identity="extractimports" parent="none"]
|
|
179
|
+
// CIL[DOC-MACRO purpose="Implements extractimports logic in cortex.functions.custom_cil-callmap"]
|
|
180
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Execute extractimports and return its computed result"]
|
|
181
|
+
// CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[]"]
|
|
182
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="return value from function execution" errors="throws on invalid input or runtime failure" side_effects="none"]
|
|
183
|
+
// CIL[DOC-MICRO logic_summary="Provides extractimports with extractImports(source: string inputs, handling internal flow and returning a result" notable_decisions="[]"]
|
|
184
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
185
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
186
|
+
// CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
187
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
188
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
189
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
190
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
191
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
192
|
+
export function extractImports(source: string): ExtractedImport[] {
|
|
193
|
+
const results: ExtractedImport[] = []
|
|
194
|
+
|
|
195
|
+
const importRe = /^import\s+([\s\S]*?)\s+from\s+['"]([^'"]+)['"]/gm
|
|
196
|
+
let m: RegExpExecArray | null
|
|
197
|
+
while ((m = importRe.exec(source)) !== null) {
|
|
198
|
+
const specifierBlock = m[1].trim()
|
|
199
|
+
const fromPath = m[2]
|
|
200
|
+
|
|
201
|
+
let symbols: string[] = []
|
|
202
|
+
let isDefault = false
|
|
203
|
+
|
|
204
|
+
if (specifierBlock.startsWith('{')) {
|
|
205
|
+
|
|
206
|
+
const inner = specifierBlock.replace(/^\{|\}$/g, '').trim()
|
|
207
|
+
symbols = inner.split(',').map(s => {
|
|
208
|
+
const parts = s.trim().split(/\s+as\s+/)
|
|
209
|
+
return (parts[parts.length - 1] || '').trim()
|
|
210
|
+
}).filter(Boolean)
|
|
211
|
+
} else if (specifierBlock.startsWith('*')) {
|
|
212
|
+
|
|
213
|
+
const asMatch = specifierBlock.match(/\*\s+as\s+(\w+)/)
|
|
214
|
+
if (asMatch) symbols = [asMatch[1]]
|
|
215
|
+
} else {
|
|
216
|
+
|
|
217
|
+
const defaultMatch = specifierBlock.match(/^(\w+)/)
|
|
218
|
+
if (defaultMatch) { symbols = [defaultMatch[1]]; isDefault = true }
|
|
219
|
+
const namedMatch = specifierBlock.match(/\{([^}]+)\}/)
|
|
220
|
+
if (namedMatch) {
|
|
221
|
+
const named = namedMatch[1].split(',').map(s => s.trim().split(/\s+as\s+/).pop()!.trim()).filter(Boolean)
|
|
222
|
+
symbols = [...symbols, ...named]
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
results.push({ from_path: fromPath, symbols, is_default: isDefault })
|
|
227
|
+
}
|
|
228
|
+
return results
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
// CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractimports_1784235266"]
|
|
239
|
+
// CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractcalls_1784235266" type="function" identity="extractcalls" parent="none"]
|
|
240
|
+
// CIL[DOC-MACRO purpose="Implements extractcalls logic in cortex.functions.custom_cil-callmap"]
|
|
241
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Execute extractcalls and return its computed result"]
|
|
242
|
+
// CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[]"]
|
|
243
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="return value from function execution" errors="throws on invalid input or runtime failure" side_effects="none"]
|
|
244
|
+
// CIL[DOC-MICRO logic_summary="Provides extractcalls with extractCalls(source: string inputs, handling internal flow and returning a result" notable_decisions="[]"]
|
|
245
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
246
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
247
|
+
// CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
248
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
249
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
250
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
251
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
252
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
253
|
+
export function extractCalls(source: string): ExtractedCall[] {
|
|
254
|
+
const seen = new Set<string>()
|
|
255
|
+
const results: ExtractedCall[] = []
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
const callRe = /(await\s+)?(?:[\w$]+\.)*?([\w$]{2,})\s*\(/g
|
|
259
|
+
let m: RegExpExecArray | null
|
|
260
|
+
while ((m = callRe.exec(source)) !== null) {
|
|
261
|
+
const isAwait = !!m[1]
|
|
262
|
+
const calleeName = m[2]
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
if (['if', 'for', 'while', 'switch', 'catch', 'return', 'new', 'typeof', 'instanceof', 'function'].includes(calleeName)) continue
|
|
266
|
+
if (calleeName.length < 3) continue
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
if (['ctx', 'req', 'res', 'data', 'props', 'state', 'params', 'config', 'options', 'args'].includes(calleeName)) continue
|
|
270
|
+
|
|
271
|
+
if (seen.has(calleeName)) continue
|
|
272
|
+
seen.add(calleeName)
|
|
273
|
+
results.push({ callee_name: calleeName, is_await: isAwait })
|
|
274
|
+
}
|
|
275
|
+
return results
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
// CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractcalls_1784235266"]
|
|
286
|
+
// CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractsymbolreferences_1784235266" type="function" identity="extractsymbolreferences" parent="none"]
|
|
287
|
+
// CIL[DOC-MACRO purpose="Find symbol/name references from one chunk to other chunk identities"]
|
|
288
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Detect non-call references to exported chunk names/types to enrich the call graph"]
|
|
289
|
+
// CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[]"]
|
|
290
|
+
// CIL[DOC-CONTRACT inputs="source string, candidate symbol list" outputs="matching symbol names" errors="none" side_effects="none"]
|
|
291
|
+
// CIL[DOC-MICRO logic_summary="Builds a single regex from chunk identities and returns the set of names found as whole-word tokens in the source" notable_decisions="[]"]
|
|
292
|
+
// CIL[DOC-CONFIDENCE pass="first" score="0.85" flags="possible_false_positives"]
|
|
293
|
+
// CIL[DOC-STABILITY stability="experimental"]
|
|
294
|
+
function escapeRegex(s: string): string {
|
|
295
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function extractSymbolReferences(source: string, candidateNames: string[], ownName?: string): string[] {
|
|
299
|
+
const reserved = new Set(['if','for','while','switch','catch','return','new','typeof','instanceof','function','const','let','var','class','interface','type','enum','export','import','from','await','async','true','false','null','undefined','this','super','extends','implements','as','in','of','with','yield'])
|
|
300
|
+
const candidates = candidateNames
|
|
301
|
+
.filter(n => n && n !== ownName && n.length >= 2 && !reserved.has(n))
|
|
302
|
+
.sort((a, b) => b.length - a.length)
|
|
303
|
+
if (candidates.length === 0) return []
|
|
304
|
+
|
|
305
|
+
const pattern = new RegExp(`(?:^|[^A-Za-z0-9_$])(${candidates.map(escapeRegex).join('|')})(?=[^A-Za-z0-9_$]|$)`, 'g')
|
|
306
|
+
const seen = new Set<string>()
|
|
307
|
+
let m: RegExpExecArray | null
|
|
308
|
+
while ((m = pattern.exec(source)) !== null) {
|
|
309
|
+
seen.add(m[1])
|
|
310
|
+
}
|
|
311
|
+
return [...seen]
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
// CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractsymbolreferences_1784235266"]
|
|
318
|
+
// CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractexports_1784235266" type="function" identity="extractexports" parent="none"]
|
|
319
|
+
// CIL[DOC-MACRO purpose="Implements extractexports logic in cortex.functions.custom_cil-callmap"]
|
|
320
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Execute extractexports and return its computed result"]
|
|
321
|
+
// CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[]"]
|
|
322
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="return value from function execution" errors="throws on invalid input or runtime failure" side_effects="none"]
|
|
323
|
+
// CIL[DOC-MICRO logic_summary="Provides extractexports with extractExports(source: string inputs, handling internal flow and returning a result" notable_decisions="[]"]
|
|
324
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
325
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
326
|
+
// CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
327
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
328
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
329
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
330
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
331
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
332
|
+
export function extractExports(source: string): string[] {
|
|
333
|
+
const exports: string[] = []
|
|
334
|
+
|
|
335
|
+
const exportRe = /^export\s+(?:default\s+)?(?:async\s+)?(?:function|class|const|let|var|type|interface|enum)\s+(\w+)/gm
|
|
336
|
+
let m: RegExpExecArray | null
|
|
337
|
+
while ((m = exportRe.exec(source)) !== null) {
|
|
338
|
+
exports.push(m[1])
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
const namedRe = /^export\s+\{([^}]+)\}/gm
|
|
342
|
+
while ((m = namedRe.exec(source)) !== null) {
|
|
343
|
+
const named = m[1].split(',').map(s => s.trim().split(/\s+as\s+/).pop()!.trim()).filter(Boolean)
|
|
344
|
+
exports.push(...named)
|
|
345
|
+
}
|
|
346
|
+
return [...new Set(exports)]
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
// CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractexports_1784235266"]
|
|
358
|
+
// CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_resolveimportpath_1784235266" type="function" identity="resolveimportpath" parent="none"]
|
|
359
|
+
// CIL[DOC-MACRO purpose="Implements resolveimportpath logic in cortex.functions.custom_cil-callmap"]
|
|
360
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Execute resolveimportpath and return its computed result"]
|
|
361
|
+
// CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[]"]
|
|
362
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="return value from function execution" errors="throws on invalid input or runtime failure" side_effects="none"]
|
|
363
|
+
// CIL[DOC-MICRO logic_summary="Provides resolveimportpath with resolveImportPath(fromFilePath: string, importSpecifier: string inputs, handling internal flow and returning a result" notable_decisions="[]"]
|
|
364
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
365
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
366
|
+
// CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
367
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
368
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
369
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
370
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
371
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
372
|
+
function resolveImportPath(fromFilePath: string, importSpecifier: string): string | null {
|
|
373
|
+
|
|
374
|
+
if (!importSpecifier.startsWith('.')) return null
|
|
375
|
+
|
|
376
|
+
const fromDir = fromFilePath.split('/').slice(0, -1).join('/')
|
|
377
|
+
const segments = `${fromDir}/${importSpecifier}`.split('/')
|
|
378
|
+
const resolved: string[] = []
|
|
379
|
+
|
|
380
|
+
for (const seg of segments) {
|
|
381
|
+
if (seg === '..') resolved.pop()
|
|
382
|
+
else if (seg !== '.') resolved.push(seg)
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
const base = resolved.join('/')
|
|
386
|
+
|
|
387
|
+
return base
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
// CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_resolveimportpath_1784235266"]
|
|
395
|
+
// CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_upsertlink_1784235266" type="function" identity="upsertlink" parent="none"]
|
|
396
|
+
// CIL[DOC-MACRO purpose="Implements upsertlink logic in cortex.functions.custom_cil-callmap"]
|
|
397
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Execute upsertlink and return its computed result"]
|
|
398
|
+
// CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[]"]
|
|
399
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="return value from function execution" errors="throws on invalid input or runtime failure" side_effects="none"]
|
|
400
|
+
// CIL[DOC-MICRO logic_summary="Provides upsertlink with upsertLink( inputs, handling internal flow and returning a result" notable_decisions="[]"]
|
|
401
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
402
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
403
|
+
// CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
404
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
405
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
406
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
407
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
408
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
409
|
+
export async function upsertLink(
|
|
410
|
+
ctx: any,
|
|
411
|
+
sourceItem: any,
|
|
412
|
+
targetItem: any,
|
|
413
|
+
linkTypeId: string,
|
|
414
|
+
metadata: Record<string, any> = {}
|
|
415
|
+
): Promise<boolean> {
|
|
416
|
+
|
|
417
|
+
const { data: existing } = await adminDb
|
|
418
|
+
.from('links')
|
|
419
|
+
.select('id')
|
|
420
|
+
.eq('source_id', sourceItem.id)
|
|
421
|
+
.eq('target_id', targetItem.id)
|
|
422
|
+
.eq('link_type_id', linkTypeId)
|
|
423
|
+
.maybeSingle()
|
|
424
|
+
|
|
425
|
+
if (existing) return false
|
|
426
|
+
|
|
427
|
+
const sourceType = sourceItem.data?.kb_type
|
|
428
|
+
const targetType = targetItem.data?.kb_type
|
|
429
|
+
if (!sourceType || !targetType) return false
|
|
430
|
+
|
|
431
|
+
try {
|
|
432
|
+
await adminCreate(ctx, {
|
|
433
|
+
entity: 'links',
|
|
434
|
+
type_slug: 'link',
|
|
435
|
+
source_id: sourceItem.id,
|
|
436
|
+
source_type: sourceType,
|
|
437
|
+
target_id: targetItem.id,
|
|
438
|
+
target_type: targetType,
|
|
439
|
+
link_type_id: linkTypeId,
|
|
440
|
+
metadata,
|
|
441
|
+
})
|
|
442
|
+
return true
|
|
443
|
+
} catch (err: any) {
|
|
444
|
+
console.error('upsertLink failed:', err?.message || err)
|
|
445
|
+
return false
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
// CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_upsertlink_1784235266"]
|
|
454
|
+
// CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_clearprojectlinks_1784235266" type="function" identity="clearprojectlinks" parent="none"]
|
|
455
|
+
async function clearProjectLinks(projectId: string, linkTypeIds: string[]): Promise<number> {
|
|
456
|
+
const [{ data: fileItems }, { data: chunkItems }] = await Promise.all([
|
|
457
|
+
adminDb
|
|
458
|
+
.from('items')
|
|
459
|
+
.select('id')
|
|
460
|
+
.filter('data->>project_id', 'eq', projectId)
|
|
461
|
+
.filter('data->>kb_type', 'eq', 'cil_file')
|
|
462
|
+
.eq('is_active', true),
|
|
463
|
+
adminDb
|
|
464
|
+
.from('items')
|
|
465
|
+
.select('id')
|
|
466
|
+
.filter('data->>project_id', 'eq', projectId)
|
|
467
|
+
.filter('data->>kb_type', 'eq', 'cil_chunk')
|
|
468
|
+
.eq('is_active', true),
|
|
469
|
+
])
|
|
470
|
+
|
|
471
|
+
const ids = [
|
|
472
|
+
...(fileItems || []).map((f: any) => f.id),
|
|
473
|
+
...(chunkItems || []).map((c: any) => c.id),
|
|
474
|
+
]
|
|
475
|
+
if (!ids.length) return 0
|
|
476
|
+
|
|
477
|
+
let deleted = 0
|
|
478
|
+
for (const ltId of linkTypeIds.filter(Boolean)) {
|
|
479
|
+
for (let i = 0; i < ids.length; i += UUID_IN_LIMIT) {
|
|
480
|
+
const { data: deletedRows } = await adminDb
|
|
481
|
+
.from('links')
|
|
482
|
+
.delete()
|
|
483
|
+
.eq('link_type_id', ltId)
|
|
484
|
+
.in('source_id', ids.slice(i, i + UUID_IN_LIMIT))
|
|
485
|
+
.select('id')
|
|
486
|
+
deleted += (deletedRows || []).length
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
return deleted
|
|
490
|
+
}
|
|
491
|
+
// CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_clearprojectlinks_1784235266"]
|
|
492
|
+
// CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_mapfile_1784235266" type="function" identity="mapfile" parent="none"]
|
|
493
|
+
// CIL[DOC-MACRO purpose="Implements mapfile logic in cortex.functions.custom_cil-callmap"]
|
|
494
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Execute mapfile and return its computed result"]
|
|
495
|
+
// CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[]"]
|
|
496
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="return value from function execution" errors="throws on invalid input or runtime failure" side_effects="none"]
|
|
497
|
+
// CIL[DOC-MICRO logic_summary="Provides mapfile with mapFile( inputs, handling internal flow and returning a result" notable_decisions="[]"]
|
|
498
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
499
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
500
|
+
// CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
501
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
502
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
503
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
504
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
505
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
506
|
+
export async function mapFile(
|
|
507
|
+
ctx: any,
|
|
508
|
+
fileItem: any,
|
|
509
|
+
projectId: string,
|
|
510
|
+
allChunksByFile: Map<string, any[]>,
|
|
511
|
+
chunksByName: Map<string, any>,
|
|
512
|
+
fileItemsByPath: Map<string, any>,
|
|
513
|
+
importsLinkTypeId: string,
|
|
514
|
+
callsLinkTypeId: string,
|
|
515
|
+
exportsLinkTypeId: string
|
|
516
|
+
): Promise<{ imports_created: number; calls_created: number; exports_created: number }> {
|
|
517
|
+
let importsCreated = 0, callsCreated = 0, exportsCreated = 0
|
|
518
|
+
|
|
519
|
+
const filePath: string = fileItem.data?.file_path || fileItem.title
|
|
520
|
+
const chunksInFile = allChunksByFile.get(fileItem.id) || []
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
const allChunkNames = Array.from(chunksByName.keys())
|
|
524
|
+
|
|
525
|
+
for (const chunk of chunksInFile) {
|
|
526
|
+
const codeContent: string = chunk.data?.code_content || ''
|
|
527
|
+
if (!codeContent) continue
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
const calls = extractCalls(codeContent)
|
|
531
|
+
for (const call of calls) {
|
|
532
|
+
const targetChunk = chunksByName.get(call.callee_name)
|
|
533
|
+
if (!targetChunk || targetChunk.id === chunk.id) continue
|
|
534
|
+
const created = await upsertLink(ctx, chunk, targetChunk, callsLinkTypeId, {
|
|
535
|
+
callee_name: call.callee_name,
|
|
536
|
+
is_await: call.is_await,
|
|
537
|
+
})
|
|
538
|
+
if (created) callsCreated++
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
const symbolRefs = extractSymbolReferences(codeContent, allChunkNames, chunk.data?.chunk_name || '')
|
|
543
|
+
for (const refName of symbolRefs) {
|
|
544
|
+
const targetChunk = chunksByName.get(refName)
|
|
545
|
+
if (!targetChunk || targetChunk.id === chunk.id) continue
|
|
546
|
+
const created = await upsertLink(ctx, chunk, targetChunk, callsLinkTypeId, {
|
|
547
|
+
callee_name: refName,
|
|
548
|
+
is_symbol_reference: true,
|
|
549
|
+
})
|
|
550
|
+
if (created) callsCreated++
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
const fullFileContent = chunksInFile.map((c: any) => c.data?.code_content || '').join('\n')
|
|
557
|
+
const imports = extractImports(fullFileContent)
|
|
558
|
+
|
|
559
|
+
for (const imp of imports) {
|
|
560
|
+
const resolvedBase = resolveImportPath(filePath, imp.from_path)
|
|
561
|
+
if (!resolvedBase) continue
|
|
562
|
+
|
|
563
|
+
|
|
564
|
+
const targetFile =
|
|
565
|
+
fileItemsByPath.get(resolvedBase) ||
|
|
566
|
+
fileItemsByPath.get(resolvedBase + '.ts') ||
|
|
567
|
+
fileItemsByPath.get(resolvedBase + '.tsx') ||
|
|
568
|
+
fileItemsByPath.get(resolvedBase + '/index.ts') ||
|
|
569
|
+
fileItemsByPath.get(resolvedBase + '/index.tsx')
|
|
570
|
+
|
|
571
|
+
if (!targetFile || targetFile.id === fileItem.id) continue
|
|
572
|
+
|
|
573
|
+
const created = await upsertLink(ctx, fileItem, targetFile, importsLinkTypeId, {
|
|
574
|
+
symbols: imp.symbols,
|
|
575
|
+
is_default: imp.is_default,
|
|
576
|
+
specifier: imp.from_path,
|
|
577
|
+
})
|
|
578
|
+
if (created) importsCreated++
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
const exportedNames = extractExports(fullFileContent)
|
|
583
|
+
for (const exportedName of exportedNames) {
|
|
584
|
+
const chunk = chunksByName.get(exportedName)
|
|
585
|
+
if (!chunk) continue
|
|
586
|
+
const created = await upsertLink(ctx, chunk, fileItem, exportsLinkTypeId, {
|
|
587
|
+
exported_name: exportedName,
|
|
588
|
+
})
|
|
589
|
+
if (created) exportsCreated++
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
return { imports_created: importsCreated, calls_created: callsCreated, exports_created: exportsCreated }
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
|
|
598
|
+
|
|
599
|
+
|
|
600
|
+
// CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_mapfile_1784235266"]
|
|
601
|
+
// CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_markfilepass4bcomplete_1784235266" type="function" identity="markfilepass4bcomplete" parent="none"]
|
|
602
|
+
// CIL[DOC-MACRO purpose="Implements markfilepass4bcomplete logic in cortex.functions.custom_cil-callmap"]
|
|
603
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Execute markfilepass4bcomplete and return its computed result"]
|
|
604
|
+
// CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[]"]
|
|
605
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="return value from function execution" errors="throws on invalid input or runtime failure" side_effects="none"]
|
|
606
|
+
// CIL[DOC-MICRO logic_summary="Provides markfilepass4bcomplete with markFilePass4bComplete( inputs, handling internal flow and returning a result" notable_decisions="[]"]
|
|
607
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
608
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
609
|
+
// CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
610
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
611
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
612
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
613
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
614
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
615
|
+
async function markFilePass4bComplete(
|
|
616
|
+
ctx: any,
|
|
617
|
+
fileItem: any,
|
|
618
|
+
tree: FileTreeNode | null,
|
|
619
|
+
secondPass = false,
|
|
620
|
+
projectItem?: any
|
|
621
|
+
): Promise<void> {
|
|
622
|
+
const cil_file_status = secondPass ? 'pass8_complete' : 'pass4b_complete'
|
|
623
|
+
const pipeline_status = secondPass ? '10-mapped' : '7-mapped'
|
|
624
|
+
const currentFileStatus = getFileStatus(fileItem)
|
|
625
|
+
const filePath: string = fileItem.data?.file_path
|
|
626
|
+
|
|
627
|
+
|
|
628
|
+
if (rank(currentFileStatus) < rank(cil_file_status)) {
|
|
629
|
+
const updateCtx = { ...ctx, query: { ...(ctx.query || {}), entity: 'items', id: fileItem.id } }
|
|
630
|
+
await adminUpdate(updateCtx, {
|
|
631
|
+
data: {
|
|
632
|
+
...fileItem.data,
|
|
633
|
+
status: cil_file_status,
|
|
634
|
+
last_status_at: new Date().toISOString(),
|
|
635
|
+
},
|
|
636
|
+
}).catch((e: any) => console.error(`mark ${cil_file_status} failed:`, e.message))
|
|
637
|
+
}
|
|
638
|
+
if (tree) updateTreeNodeStatus(tree, fileItem.id, cil_file_status)
|
|
639
|
+
|
|
640
|
+
|
|
641
|
+
const projectId: string = fileItem.data?.project_id
|
|
642
|
+
if (!filePath || !projectId) return
|
|
643
|
+
|
|
644
|
+
let projItem = projectItem
|
|
645
|
+
if (!projItem) {
|
|
646
|
+
const { data } = await adminDb.from('items').select('id, data').eq('id', projectId).maybeSingle()
|
|
647
|
+
projItem = data
|
|
648
|
+
}
|
|
649
|
+
if (!projItem) return
|
|
650
|
+
|
|
651
|
+
const currentPipelineStatus = projItem.data?.file_statuses?.[filePath]
|
|
652
|
+
if (rank(currentPipelineStatus) >= rank(pipeline_status)) return
|
|
653
|
+
|
|
654
|
+
const fileStatuses = { ...(projItem.data?.file_statuses || {}) }
|
|
655
|
+
fileStatuses[filePath] = pipeline_status
|
|
656
|
+
fileStatuses[`${filePath}_updated`] = new Date().toISOString()
|
|
657
|
+
const { data: updateResult, error: updateErr } = await adminDb.from('items')
|
|
658
|
+
.update({ data: { ...projItem.data, file_statuses: fileStatuses } })
|
|
659
|
+
.eq('id', projectId)
|
|
660
|
+
.select('id')
|
|
661
|
+
if (updateErr) {
|
|
662
|
+
console.error(`pipeline status advance to ${pipeline_status} failed:`, updateErr.message)
|
|
663
|
+
return
|
|
664
|
+
}
|
|
665
|
+
console.log(`pipeline status advance to ${pipeline_status} result:`, JSON.stringify(updateResult))
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
if (projectItem) {
|
|
669
|
+
if (!projectItem.data) projectItem.data = {}
|
|
670
|
+
projectItem.data.file_statuses = fileStatuses
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
|
|
677
|
+
|
|
678
|
+
|
|
679
|
+
// CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_markfilepass4bcomplete_1784235266"]
|
|
680
|
+
// CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_istestfile_1784235266" type="function" identity="istestfile" parent="none"]
|
|
681
|
+
// CIL[DOC-MACRO purpose="Implements istestfile logic in cortex.functions.custom_cil-callmap"]
|
|
682
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Execute istestfile and return its computed result"]
|
|
683
|
+
// CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[]"]
|
|
684
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="return value from function execution" errors="throws on invalid input or runtime failure" side_effects="none"]
|
|
685
|
+
// CIL[DOC-MICRO logic_summary="Provides istestfile with isTestFile(filePath: string inputs, handling internal flow and returning a result" notable_decisions="[]"]
|
|
686
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
687
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
688
|
+
// CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
689
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
690
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
691
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
692
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
693
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
694
|
+
function isTestFile(filePath: string): boolean {
|
|
695
|
+
return /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(filePath) ||
|
|
696
|
+
/\/__tests__\//.test(filePath) ||
|
|
697
|
+
/\/tests?\//.test(filePath)
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
|
|
701
|
+
|
|
702
|
+
|
|
703
|
+
// CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_istestfile_1784235266"]
|
|
704
|
+
// CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_maptests_1784235266" type="function" identity="maptests" parent="none"]
|
|
705
|
+
// CIL[DOC-MACRO purpose="Implements maptests logic in cortex.functions.custom_cil-callmap"]
|
|
706
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Execute maptests and return its computed result"]
|
|
707
|
+
// CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[]"]
|
|
708
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="return value from function execution" errors="throws on invalid input or runtime failure" side_effects="none"]
|
|
709
|
+
// CIL[DOC-MICRO logic_summary="Provides maptests with mapTests( inputs, handling internal flow and returning a result" notable_decisions="[]"]
|
|
710
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
711
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
712
|
+
// CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
713
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
714
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
715
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
716
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
717
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
718
|
+
async function mapTests(
|
|
719
|
+
ctx: any,
|
|
720
|
+
projectId: string,
|
|
721
|
+
repoPath: string,
|
|
722
|
+
testedByLinkTypeId: string,
|
|
723
|
+
chunksByName: Map<string, any>
|
|
724
|
+
): Promise<{ test_files_scanned: number; tested_by_links_created: number; chunks_updated: number; errors: string[] }> {
|
|
725
|
+
const errors: string[] = []
|
|
726
|
+
let testFilesScanned = 0, linksCreated = 0, chunksUpdated = 0
|
|
727
|
+
|
|
728
|
+
const { data: allFiles } = await adminDb
|
|
729
|
+
.from('items').select('id, title, data')
|
|
730
|
+
.filter('data->>project_id', 'eq', projectId)
|
|
731
|
+
.filter('data->>kb_type', 'eq', 'cil_file')
|
|
732
|
+
.eq('is_active', true)
|
|
733
|
+
|
|
734
|
+
const testFiles = (allFiles || []).filter((f: any) => isTestFile(f.data?.file_path || f.title))
|
|
735
|
+
|
|
736
|
+
const matchesByFile = new Map<string, Set<string>>()
|
|
737
|
+
const allMatchedNames = new Set<string>()
|
|
738
|
+
|
|
739
|
+
for (const testFileItem of testFiles) {
|
|
740
|
+
const relPath: string = testFileItem.data?.file_path || testFileItem.title
|
|
741
|
+
const absPath = path.join(repoPath, relPath)
|
|
742
|
+
|
|
743
|
+
try {
|
|
744
|
+
if (!fs.existsSync(absPath)) continue
|
|
745
|
+
const source = fs.readFileSync(absPath, 'utf-8')
|
|
746
|
+
testFilesScanned++
|
|
747
|
+
|
|
748
|
+
const matchedChunkNames = new Set<string>()
|
|
749
|
+
|
|
750
|
+
const importRe = /import\s+\{([^}]+)\}/g
|
|
751
|
+
let m: RegExpExecArray | null
|
|
752
|
+
while ((m = importRe.exec(source)) !== null) {
|
|
753
|
+
const names = m[1].split(',').map(s => s.trim().split(/\s+as\s+/).shift()!.trim()).filter(Boolean)
|
|
754
|
+
for (const n of names) {
|
|
755
|
+
if (chunksByName.has(n)) matchedChunkNames.add(n)
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
const stringRe = /(?:describe|it|test|beforeEach|afterEach)\s*\(\s*['"`]([^'"`]+)['"`]/g
|
|
760
|
+
while ((m = stringRe.exec(source)) !== null) {
|
|
761
|
+
const words = m[1].split(/\W+/)
|
|
762
|
+
for (const word of words) {
|
|
763
|
+
if (chunksByName.has(word)) matchedChunkNames.add(word)
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
const callRe = /\b(\w{3,})\s*\(/g
|
|
768
|
+
while ((m = callRe.exec(source)) !== null) {
|
|
769
|
+
const name = m[1]
|
|
770
|
+
if (chunksByName.has(name)) matchedChunkNames.add(name)
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
matchesByFile.set(relPath, matchedChunkNames)
|
|
774
|
+
for (const name of matchedChunkNames) allMatchedNames.add(name)
|
|
775
|
+
} catch (err) {
|
|
776
|
+
errors.push(`${relPath}: ${err instanceof Error ? err.message : String(err)}`)
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
const matchedIds = [...allMatchedNames]
|
|
781
|
+
.map(name => chunksByName.get(name)?.id)
|
|
782
|
+
.filter(Boolean)
|
|
783
|
+
const fullChunksByName = new Map<string, any>()
|
|
784
|
+
for (let i = 0; i < matchedIds.length; i += UUID_IN_LIMIT) {
|
|
785
|
+
const { data } = await adminDb
|
|
786
|
+
.from('items')
|
|
787
|
+
.select('id, title, data')
|
|
788
|
+
.in('id', matchedIds.slice(i, i + UUID_IN_LIMIT))
|
|
789
|
+
for (const c of data || []) {
|
|
790
|
+
const name = c.data?.chunk_name
|
|
791
|
+
if (name) fullChunksByName.set(name, c)
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
for (const testFileItem of testFiles) {
|
|
796
|
+
const relPath: string = testFileItem.data?.file_path || testFileItem.title
|
|
797
|
+
const absPath = path.join(repoPath, relPath)
|
|
798
|
+
const isE2E = /e2e|cypress|playwright|integration/.test(relPath)
|
|
799
|
+
const matchedChunkNames = matchesByFile.get(relPath)
|
|
800
|
+
if (!matchedChunkNames) continue
|
|
801
|
+
|
|
802
|
+
for (const chunkName of matchedChunkNames) {
|
|
803
|
+
const chunk = fullChunksByName.get(chunkName)
|
|
804
|
+
if (!chunk) continue
|
|
805
|
+
const cd = chunk.data || {}
|
|
806
|
+
|
|
807
|
+
const created = await upsertLink(ctx, chunk, testFileItem, testedByLinkTypeId, {
|
|
808
|
+
test_path: relPath,
|
|
809
|
+
is_e2e: isE2E,
|
|
810
|
+
})
|
|
811
|
+
if (created) linksCreated++
|
|
812
|
+
|
|
813
|
+
const pathField = isE2E ? 'test_e2e_path' : 'test_unit_path'
|
|
814
|
+
const existingPath = cd[pathField]
|
|
815
|
+
if (!existingPath || existingPath === relPath) {
|
|
816
|
+
await adminUpdate({ ...ctx, query: { ...(ctx.query || {}), entity: 'items', id: chunk.id } } as any, {
|
|
817
|
+
data: { ...cd, [pathField]: relPath },
|
|
818
|
+
})
|
|
819
|
+
chunksUpdated++
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
return { test_files_scanned: testFilesScanned, tested_by_links_created: linksCreated, chunks_updated: chunksUpdated, errors }
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
|
|
828
|
+
|
|
829
|
+
|
|
830
|
+
|
|
831
|
+
// CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_maptests_1784235266"]
|
|
832
|
+
// CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_handler_1784235266" type="variable" identity="handler" parent="none"]
|
|
833
|
+
// CIL[DOC-MACRO purpose="Defines handler configuration or state in cortex.functions.custom_cil-callmap"]
|
|
834
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Hold the value and default configuration for handler"]
|
|
835
|
+
// CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[]"]
|
|
836
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="value of handler" errors="none" side_effects="none"]
|
|
837
|
+
// CIL[DOC-MICRO logic_summary="Declares handler with initial value or constant binding used by cortex.functions.custom_cil-callmap" notable_decisions="[]"]
|
|
838
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
839
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
840
|
+
// CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
841
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
842
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
843
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
844
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
845
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
846
|
+
export const handler = createHandler(async (ctx, body) => {
|
|
847
|
+
const action = ctx.query?.action
|
|
848
|
+
|
|
849
|
+
|
|
850
|
+
if (action === 'status') {
|
|
851
|
+
const projectId = ctx.query?.project_id || body?.project_id
|
|
852
|
+
if (!projectId) throw new Error('project_id is required')
|
|
853
|
+
|
|
854
|
+
const [importsTypeId, callsTypeId, exportsTypeId, testedByTypeId] = await Promise.all([
|
|
855
|
+
resolveLinkTypeId('cil_imports').catch(() => null),
|
|
856
|
+
resolveLinkTypeId('cil_calls').catch(() => null),
|
|
857
|
+
resolveLinkTypeId('cil_exports').catch(() => null),
|
|
858
|
+
resolveLinkTypeId('cil_tested_by').catch(() => null),
|
|
859
|
+
])
|
|
860
|
+
|
|
861
|
+
const { data: fileItems } = await adminDb
|
|
862
|
+
.from('items')
|
|
863
|
+
.select('id')
|
|
864
|
+
.filter('data->>project_id', 'eq', projectId)
|
|
865
|
+
.filter('data->>kb_type', 'eq', 'cil_file')
|
|
866
|
+
|
|
867
|
+
const { data: chunkItems } = await adminDb
|
|
868
|
+
.from('items')
|
|
869
|
+
.select('id')
|
|
870
|
+
.filter('data->>project_id', 'eq', projectId)
|
|
871
|
+
.filter('data->>kb_type', 'eq', 'cil_chunk')
|
|
872
|
+
|
|
873
|
+
const fileIds = (fileItems || []).map((f: any) => f.id)
|
|
874
|
+
const chunkIds = (chunkItems || []).map((c: any) => c.id)
|
|
875
|
+
|
|
876
|
+
async function countLinksForIds(typeId: string, ids: string[]): Promise<number> {
|
|
877
|
+
if (!typeId || !ids.length) return 0
|
|
878
|
+
let total = 0
|
|
879
|
+
for (let i = 0; i < ids.length; i += UUID_IN_LIMIT) {
|
|
880
|
+
const { count } = await adminDb.from('links').select('id', { count: 'exact' })
|
|
881
|
+
.eq('link_type_id', typeId).in('source_id', ids.slice(i, i + UUID_IN_LIMIT))
|
|
882
|
+
total += count || 0
|
|
883
|
+
}
|
|
884
|
+
return total
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
const importCount = await countLinksForIds(importsTypeId, fileIds)
|
|
888
|
+
const callCount = await countLinksForIds(callsTypeId, chunkIds)
|
|
889
|
+
const exportCount = await countLinksForIds(exportsTypeId, chunkIds)
|
|
890
|
+
const testedByCount = await countLinksForIds(testedByTypeId, chunkIds)
|
|
891
|
+
|
|
892
|
+
return {
|
|
893
|
+
project_id: projectId,
|
|
894
|
+
total_files: (fileItems || []).length,
|
|
895
|
+
total_chunks: (chunkItems || []).length,
|
|
896
|
+
import_links: importCount,
|
|
897
|
+
call_links: callCount,
|
|
898
|
+
export_links: exportCount,
|
|
899
|
+
tested_by_links: testedByCount,
|
|
900
|
+
total_links: importCount + callCount + exportCount + testedByCount,
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
|
|
905
|
+
if (action === 'clear') {
|
|
906
|
+
const projectId = body?.project_id
|
|
907
|
+
if (!projectId) throw new Error('project_id is required')
|
|
908
|
+
|
|
909
|
+
const [importsTypeId, callsTypeId, exportsTypeId] = await Promise.all([
|
|
910
|
+
resolveLinkTypeId('cil_imports').catch(() => null),
|
|
911
|
+
resolveLinkTypeId('cil_calls').catch(() => null),
|
|
912
|
+
resolveLinkTypeId('cil_exports').catch(() => null),
|
|
913
|
+
])
|
|
914
|
+
|
|
915
|
+
const { data: chunkItems } = await adminDb
|
|
916
|
+
.from('items').select('id')
|
|
917
|
+
.filter('data->>project_id', 'eq', projectId)
|
|
918
|
+
.filter('data->>kb_type', 'in', '(cil_chunk,cil_file)')
|
|
919
|
+
|
|
920
|
+
const ids = (chunkItems || []).map((c: any) => c.id)
|
|
921
|
+
let deleted = 0
|
|
922
|
+
|
|
923
|
+
for (const ltId of [importsTypeId, callsTypeId, exportsTypeId].filter(Boolean)) {
|
|
924
|
+
if (!ids.length) continue
|
|
925
|
+
for (let i = 0; i < ids.length; i += UUID_IN_LIMIT) {
|
|
926
|
+
const { data: deletedRows } = await adminDb.from('links')
|
|
927
|
+
.delete().eq('link_type_id', ltId!).in('source_id', ids.slice(i, i + UUID_IN_LIMIT)).select('id')
|
|
928
|
+
deleted += (deletedRows || []).length
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
|
|
933
|
+
const { data: projectItem } = await adminDb.from('items').select('id, data').eq('id', projectId).maybeSingle()
|
|
934
|
+
const fileTree = (projectItem?.data?.file_tree as FileTreeNode) || null
|
|
935
|
+
const { data: fileItems } = await adminDb
|
|
936
|
+
.from('items')
|
|
937
|
+
.select('id, data')
|
|
938
|
+
.filter('data->>project_id', 'eq', projectId)
|
|
939
|
+
.filter('data->>kb_type', 'eq', 'cil_file')
|
|
940
|
+
.eq('is_active', true)
|
|
941
|
+
|
|
942
|
+
let resetCount = 0
|
|
943
|
+
for (const fileItem of fileItems || []) {
|
|
944
|
+
if (getFileStatus(fileItem) === 'pass4b_complete') {
|
|
945
|
+
const updateCtx = { ...ctx, query: { ...(ctx.query || {}), entity: 'items', id: fileItem.id } }
|
|
946
|
+
await adminUpdate(updateCtx, {
|
|
947
|
+
data: {
|
|
948
|
+
...fileItem.data,
|
|
949
|
+
status: 'pass3_complete',
|
|
950
|
+
last_status_at: new Date().toISOString(),
|
|
951
|
+
},
|
|
952
|
+
}).catch((e: any) => console.error(`reset status ${fileItem.id}: ${e.message}`))
|
|
953
|
+
if (fileTree) updateTreeNodeStatus(fileTree, fileItem.id, 'pass3_complete')
|
|
954
|
+
resetCount++
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
if (fileTree && projectItem) {
|
|
958
|
+
await saveProjectTree(ctx, projectId, fileTree, { last_ingested_at: new Date().toISOString() })
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
return { project_id: projectId, deleted_links: deleted, reset_files: resetCount }
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
|
|
965
|
+
if (action === 'map_file') {
|
|
966
|
+
const fileId = body?.file_id
|
|
967
|
+
if (!fileId) throw new Error('file_id is required')
|
|
968
|
+
|
|
969
|
+
const { data: fileItem } = await adminDb
|
|
970
|
+
.from('items').select('id, title, data').eq('id', fileId).maybeSingle()
|
|
971
|
+
if (!fileItem) throw new Error(`File not found: ${fileId}`)
|
|
972
|
+
|
|
973
|
+
const projectId = fileItem.data?.project_id
|
|
974
|
+
if (!projectId) throw new Error('File has no project_id')
|
|
975
|
+
|
|
976
|
+
const [importsTypeId, callsTypeId, exportsTypeId] = await Promise.all([
|
|
977
|
+
resolveLinkTypeId('cil_imports'),
|
|
978
|
+
resolveLinkTypeId('cil_calls'),
|
|
979
|
+
resolveLinkTypeId('cil_exports'),
|
|
980
|
+
])
|
|
981
|
+
|
|
982
|
+
|
|
983
|
+
const { data: allFiles } = await adminDb
|
|
984
|
+
.from('items').select('id, title, data')
|
|
985
|
+
.filter('data->>project_id', 'eq', projectId)
|
|
986
|
+
.filter('data->>kb_type', 'eq', 'cil_file').eq('is_active', true)
|
|
987
|
+
|
|
988
|
+
const { data: allChunks } = await adminDb
|
|
989
|
+
.from('items').select('id, title, data')
|
|
990
|
+
.filter('data->>project_id', 'eq', projectId)
|
|
991
|
+
.filter('data->>kb_type', 'eq', 'cil_chunk').eq('is_active', true)
|
|
992
|
+
|
|
993
|
+
const fileItemsByPath = new Map((allFiles || []).map((f: any) => [f.data?.file_path || f.title, f]))
|
|
994
|
+
const chunksByName = new Map((allChunks || []).map((c: any) => [c.data?.chunk_name || '', c]))
|
|
995
|
+
const allChunksByFile = new Map<string, any[]>()
|
|
996
|
+
for (const c of allChunks || []) {
|
|
997
|
+
const fid = c.data?.file_id
|
|
998
|
+
if (!fid) continue
|
|
999
|
+
if (!allChunksByFile.has(fid)) allChunksByFile.set(fid, [])
|
|
1000
|
+
allChunksByFile.get(fid)!.push(c)
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
const result = await mapFile(
|
|
1004
|
+
fileItem, projectId,
|
|
1005
|
+
allChunksByFile, chunksByName, fileItemsByPath,
|
|
1006
|
+
importsTypeId, callsTypeId, exportsTypeId
|
|
1007
|
+
)
|
|
1008
|
+
|
|
1009
|
+
return { file_id: fileId, ...result }
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
|
|
1013
|
+
if (action === 'map_tests') {
|
|
1014
|
+
const projectId = body?.project_id
|
|
1015
|
+
if (!projectId) throw new Error('project_id is required')
|
|
1016
|
+
|
|
1017
|
+
|
|
1018
|
+
const { data: projectItem } = await adminDb
|
|
1019
|
+
.from('items').select('data').eq('id', projectId).maybeSingle()
|
|
1020
|
+
const repoPath: string = projectItem?.data?.repo_path || body?.repo_path || ''
|
|
1021
|
+
if (!repoPath) throw new Error('Project has no repo_path — pass repo_path in body')
|
|
1022
|
+
|
|
1023
|
+
const testedByTypeId = await resolveLinkTypeId('cil_tested_by')
|
|
1024
|
+
const { data: allChunks } = await adminDb
|
|
1025
|
+
.from('items')
|
|
1026
|
+
.select('id, data->>chunk_name, data->>kb_type')
|
|
1027
|
+
.filter('data->>project_id', 'eq', projectId)
|
|
1028
|
+
.filter('data->>kb_type', 'eq', 'cil_chunk')
|
|
1029
|
+
.eq('is_active', true)
|
|
1030
|
+
const chunksByName = new Map<string, any>()
|
|
1031
|
+
for (const c of allChunks || []) {
|
|
1032
|
+
const name = c.chunk_name
|
|
1033
|
+
if (name) chunksByName.set(name, { id: c.id, data: { chunk_name: c.chunk_name, kb_type: c.kb_type || 'cil_chunk' } })
|
|
1034
|
+
}
|
|
1035
|
+
const result = await mapTests(ctx, projectId, repoPath, testedByTypeId, chunksByName)
|
|
1036
|
+
return { project_id: projectId, repo_path: repoPath, ...result }
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
|
|
1040
|
+
|
|
1041
|
+
|
|
1042
|
+
|
|
1043
|
+
|
|
1044
|
+
|
|
1045
|
+
if (action === 'map_project') {
|
|
1046
|
+
const projectId = body?.project_id
|
|
1047
|
+
if (!projectId) throw new Error('project_id is required')
|
|
1048
|
+
|
|
1049
|
+
const pageLimit = Math.min(parseInt(body?.limit || '5', 10), 15)
|
|
1050
|
+
const pageOffset = parseInt(body?.offset || '0', 10)
|
|
1051
|
+
const filePath = body?.file_path || undefined
|
|
1052
|
+
const force = body?.force_regenerate ?? body?.force ?? false
|
|
1053
|
+
const secondPass = body?.second_pass ?? false
|
|
1054
|
+
|
|
1055
|
+
const targetPipelineStatus = secondPass ? '10-mapped' : '7-mapped'
|
|
1056
|
+
|
|
1057
|
+
const [importsTypeId, callsTypeId, exportsTypeId, testedByTypeId] = await Promise.all([
|
|
1058
|
+
resolveLinkTypeId('cil_imports'),
|
|
1059
|
+
resolveLinkTypeId('cil_calls'),
|
|
1060
|
+
resolveLinkTypeId('cil_exports'),
|
|
1061
|
+
resolveLinkTypeId('cil_tested_by').catch(() => null),
|
|
1062
|
+
])
|
|
1063
|
+
|
|
1064
|
+
if (force && pageOffset === 0) {
|
|
1065
|
+
await clearProjectLinks(projectId, [importsTypeId, callsTypeId, exportsTypeId, testedByTypeId])
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
|
|
1069
|
+
const { data: projectItem } = await adminDb.from('items').select('id, data').eq('id', projectId).maybeSingle()
|
|
1070
|
+
const selectedExtensions = body?.selected_extensions || (projectItem?.data?.selected_extensions as string[] | undefined)
|
|
1071
|
+
const selectedPaths: string[] = body?.selected_paths || projectItem?.data?.selected_paths || []
|
|
1072
|
+
const fileTree = (projectItem?.data?.file_tree as FileTreeNode) || null
|
|
1073
|
+
|
|
1074
|
+
|
|
1075
|
+
const sourceFilePaths = filePath
|
|
1076
|
+
? [filePath]
|
|
1077
|
+
: force
|
|
1078
|
+
? selectedPaths
|
|
1079
|
+
: getMapSourceFilePaths(projectItem, secondPass)
|
|
1080
|
+
|
|
1081
|
+
let filesQ = adminDb.from('items').select('id, title, data')
|
|
1082
|
+
.filter('data->>project_id', 'eq', projectId)
|
|
1083
|
+
.filter('data->>kb_type', 'eq', 'cil_file').eq('is_active', true)
|
|
1084
|
+
.order('id')
|
|
1085
|
+
if (filePath) filesQ = filesQ.filter('data->>file_path', 'eq', filePath)
|
|
1086
|
+
|
|
1087
|
+
const [filesResult, allChunksMinimalResult] = await Promise.all([
|
|
1088
|
+
filesQ,
|
|
1089
|
+
adminDb.from('items').select('id, data->>chunk_name, data->>kb_type')
|
|
1090
|
+
.filter('data->>project_id', 'eq', projectId)
|
|
1091
|
+
.filter('data->>kb_type', 'eq', 'cil_chunk')
|
|
1092
|
+
.eq('is_active', true),
|
|
1093
|
+
])
|
|
1094
|
+
|
|
1095
|
+
const allFiles = filesResult.data || []
|
|
1096
|
+
const allChunksMinimal = allChunksMinimalResult.data || []
|
|
1097
|
+
|
|
1098
|
+
const fileItemsByPath = new Map(allFiles.map((f: any) => [f.data?.file_path || f.title, f]))
|
|
1099
|
+
|
|
1100
|
+
const chunksByName = new Map<string, any>()
|
|
1101
|
+
for (const c of allChunksMinimal) {
|
|
1102
|
+
const name = c.chunk_name
|
|
1103
|
+
if (name) chunksByName.set(name, { id: c.id, data: { chunk_name: c.chunk_name, kb_type: c.kb_type || 'cil_chunk' } })
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
const mappedFileStatus = secondPass ? 'pass8_complete' : 'pass4b_complete'
|
|
1107
|
+
const syncFiles = allFiles.filter((f: any) => {
|
|
1108
|
+
const fp = f.data?.file_path || f.title
|
|
1109
|
+
const status = getFileStatus(f)
|
|
1110
|
+
const ext = f.data?.extension as string || ''
|
|
1111
|
+
const extMatch = (selectedExtensions || []).length === 0 || (selectedExtensions || []).includes(ext)
|
|
1112
|
+
return status === mappedFileStatus
|
|
1113
|
+
&& rank(projectItem?.data?.file_statuses?.[fp]) < rank(targetPipelineStatus)
|
|
1114
|
+
&& isSelectedPath(fp, selectedPaths)
|
|
1115
|
+
&& extMatch
|
|
1116
|
+
})
|
|
1117
|
+
for (const fileItem of syncFiles) {
|
|
1118
|
+
await markFilePass4bComplete(ctx, fileItem, fileTree, secondPass, projectItem)
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
const eligibleFiles = allFiles.filter((f: any) => {
|
|
1122
|
+
const fp = f.data?.file_path || f.title
|
|
1123
|
+
const ext = f.data?.extension as string || ''
|
|
1124
|
+
const extMatch = (selectedExtensions || []).length === 0 || (selectedExtensions || []).includes(ext)
|
|
1125
|
+
if (filePath && fp !== filePath) return false
|
|
1126
|
+
return sourceFilePaths.includes(fp) && isSelectedPath(fp, selectedPaths) && extMatch
|
|
1127
|
+
})
|
|
1128
|
+
|
|
1129
|
+
const totalFiles = eligibleFiles.length
|
|
1130
|
+
const pageFiles = eligibleFiles.slice(pageOffset, pageOffset + pageLimit)
|
|
1131
|
+
|
|
1132
|
+
const pageFilePaths = pageFiles.map(f => f.data?.file_path || f.title)
|
|
1133
|
+
let pageChunks: any[] = []
|
|
1134
|
+
if (pageFilePaths.length > 0) {
|
|
1135
|
+
const { data } = await adminDb.from('items').select('id, title, data')
|
|
1136
|
+
.filter('data->>project_id', 'eq', projectId)
|
|
1137
|
+
.filter('data->>kb_type', 'eq', 'cil_chunk')
|
|
1138
|
+
.eq('is_active', true)
|
|
1139
|
+
.in('data->>file_path' as any, pageFilePaths)
|
|
1140
|
+
pageChunks = data || []
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
const allChunksByFile = new Map<string, any[]>()
|
|
1144
|
+
for (const c of pageChunks) {
|
|
1145
|
+
const name = c.data?.chunk_name || ''
|
|
1146
|
+
if (name) chunksByName.set(name, c)
|
|
1147
|
+
const fid = c.data?.file_id
|
|
1148
|
+
if (!fid) continue
|
|
1149
|
+
if (!allChunksByFile.has(fid)) allChunksByFile.set(fid, [])
|
|
1150
|
+
allChunksByFile.get(fid)!.push(c)
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
if (!chunksByName.size) {
|
|
1154
|
+
return { project_id: projectId, file_path: filePath || null, message: 'No chunks found — run Pass 1 + Pass 2 first', imports_created: 0, calls_created: 0, exports_created: 0, has_more: false }
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
let totalImports = 0, totalCalls = 0, totalExports = 0
|
|
1158
|
+
const errors: string[] = []
|
|
1159
|
+
|
|
1160
|
+
for (const fileItem of pageFiles) {
|
|
1161
|
+
try {
|
|
1162
|
+
const result = await mapFile(
|
|
1163
|
+
ctx, fileItem, projectId,
|
|
1164
|
+
allChunksByFile, chunksByName, fileItemsByPath,
|
|
1165
|
+
importsTypeId, callsTypeId, exportsTypeId
|
|
1166
|
+
)
|
|
1167
|
+
totalImports += result.imports_created
|
|
1168
|
+
totalCalls += result.calls_created
|
|
1169
|
+
totalExports += result.exports_created
|
|
1170
|
+
|
|
1171
|
+
|
|
1172
|
+
await markFilePass4bComplete(ctx, fileItem, fileTree, secondPass, projectItem)
|
|
1173
|
+
} catch (err) {
|
|
1174
|
+
errors.push(`${fileItem.data?.file_path || fileItem.id}: ${err instanceof Error ? err.message : String(err)}`)
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
const nextOffset = pageOffset + pageFiles.length
|
|
1179
|
+
const isLastPage = pageFiles.length === 0 || pageFiles.length < pageLimit || nextOffset >= totalFiles
|
|
1180
|
+
|
|
1181
|
+
|
|
1182
|
+
let testResult: { test_files_scanned: number; tested_by_links_created: number; chunks_updated: number; errors: string[] } | null = null
|
|
1183
|
+
if (isLastPage) {
|
|
1184
|
+
const repoPath: string = projectItem?.data?.repo_path || ''
|
|
1185
|
+
if (repoPath) {
|
|
1186
|
+
try {
|
|
1187
|
+
const testedByTypeId = await resolveLinkTypeId('cil_tested_by').catch(() => null)
|
|
1188
|
+
if (testedByTypeId) {
|
|
1189
|
+
testResult = await mapTests(ctx, projectId, repoPath, testedByTypeId, chunksByName)
|
|
1190
|
+
errors.push(...(testResult.errors || []))
|
|
1191
|
+
}
|
|
1192
|
+
} catch {
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
|
|
1198
|
+
if (fileTree) {
|
|
1199
|
+
await saveProjectTree(ctx, projectId, fileTree, { last_ingested_at: new Date().toISOString() }, projectItem)
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
return {
|
|
1203
|
+
project_id: projectId,
|
|
1204
|
+
file_path: filePath || null,
|
|
1205
|
+
total_files: totalFiles,
|
|
1206
|
+
files_processed: pageFiles.length,
|
|
1207
|
+
imports_created: totalImports,
|
|
1208
|
+
calls_created: totalCalls,
|
|
1209
|
+
exports_created: totalExports,
|
|
1210
|
+
tested_by_links_created: testResult?.tested_by_links_created ?? 0,
|
|
1211
|
+
test_files_scanned: testResult?.test_files_scanned ?? 0,
|
|
1212
|
+
chunks_updated_with_test_paths: testResult?.chunks_updated ?? 0,
|
|
1213
|
+
total_links_created: totalImports + totalCalls + totalExports + (testResult?.tested_by_links_created ?? 0),
|
|
1214
|
+
errors,
|
|
1215
|
+
has_more: !isLastPage,
|
|
1216
|
+
next_offset: !isLastPage ? nextOffset : null,
|
|
1217
|
+
done_total: pageOffset + pageFiles.length,
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
throw new Error(`Unknown action: ${action}. Valid: map_project, map_file, map_tests, status, clear`)
|
|
1222
|
+
})
|
|
1223
|
+
|
|
1224
|
+
|
|
1225
|
+
|
|
1226
|
+
|
|
1227
|
+
// CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_handler_1784235266"]
|