spine-framework 0.3.125 → 0.3.126

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (319) hide show
  1. package/.framework/cli/commands/agents.ts +35 -37
  2. package/.framework/cli/commands/auth.ts +35 -34
  3. package/.framework/cli/commands/create-app.ts +104 -40
  4. package/.framework/cli/commands/dev.ts +104 -69
  5. package/.framework/cli/commands/doctor.ts +169 -97
  6. package/.framework/cli/commands/generate.ts +82 -160
  7. package/.framework/cli/commands/init.ts +72 -34
  8. package/.framework/cli/commands/install-app.ts +260 -125
  9. package/.framework/cli/commands/items.ts +33 -44
  10. package/.framework/cli/commands/migrate.ts +122 -40
  11. package/.framework/cli/commands/migrations.ts +33 -40
  12. package/.framework/cli/commands/pipelines.ts +31 -39
  13. package/.framework/cli/commands/status.ts +47 -23
  14. package/.framework/cli/commands/system.ts +47 -37
  15. package/.framework/cli/commands/test.ts +112 -68
  16. package/.framework/cli/commands/validate-app.ts +215 -121
  17. package/.framework/cli/context.ts +112 -130
  18. package/.framework/cli/env-loader.ts +47 -18
  19. package/.framework/cli/index.ts +81 -42
  20. package/.framework/docs/runtime-types.md +1024 -0
  21. package/.framework/functions/_shared/agent-runner.ts +1296 -961
  22. package/.framework/functions/_shared/app-manifest.ts +82 -68
  23. package/.framework/functions/_shared/audit.ts +135 -83
  24. package/.framework/functions/_shared/{cil-state.ts → cil.ts} +147 -54
  25. package/.framework/functions/_shared/db.ts +80 -126
  26. package/.framework/functions/_shared/hash-api-key.ts +63 -0
  27. package/.framework/functions/_shared/index.ts +222 -347
  28. package/.framework/functions/_shared/kb.ts +319 -0
  29. package/.framework/functions/_shared/llm.ts +92 -0
  30. package/.framework/functions/_shared/logging.ts +288 -0
  31. package/.framework/functions/_shared/middleware.ts +329 -365
  32. package/.framework/functions/_shared/outcomes.ts +36 -0
  33. package/.framework/functions/_shared/permissions.ts +359 -643
  34. package/.framework/functions/_shared/pipeline-runner.ts +243 -316
  35. package/.framework/functions/_shared/principal.ts +376 -468
  36. package/.framework/functions/_shared/resolve-credentials.ts +102 -0
  37. package/.framework/functions/_shared/resolve-ids.ts +162 -14
  38. package/.framework/functions/_shared/retry-deliveries.ts +104 -0
  39. package/.framework/functions/_shared/schema-utils.ts +611 -373
  40. package/.framework/functions/_shared/testing.ts +207 -137
  41. package/.framework/functions/_shared/tracing.ts +276 -0
  42. package/.framework/functions/_shared/trigger-engine.ts +159 -211
  43. package/.framework/functions/_shared/webhook-registration.ts +95 -81
  44. package/.framework/functions/_shared/webhook-registry.ts +153 -75
  45. package/.framework/functions/account-nodes.ts +31 -53
  46. package/.framework/functions/adapters/generic-webhook-inbound.ts +56 -0
  47. package/.framework/functions/adapters/generic-webhook-outbound.ts +43 -0
  48. package/.framework/functions/adapters/openai-outbound.ts +40 -0
  49. package/.framework/functions/admin-data.ts +687 -533
  50. package/.framework/functions/admin-funnel.ts +31 -20
  51. package/.framework/functions/admin-install-funnel.ts +47 -28
  52. package/.framework/functions/admin-signals.ts +47 -29
  53. package/.framework/functions/ai-agents.ts +122 -147
  54. package/.framework/functions/ai-interactions.ts +180 -90
  55. package/.framework/functions/api-keys.ts +250 -192
  56. package/.framework/functions/apps.ts +203 -197
  57. package/.framework/functions/auth.ts +98 -91
  58. package/.framework/functions/cil-agent-ingest.ts +773 -0
  59. package/.framework/functions/cil-agent.ts +592 -0
  60. package/.framework/functions/cil-callmap.ts +1227 -0
  61. package/.framework/functions/cil-config.ts +583 -0
  62. package/.framework/functions/cil-context.ts +445 -0
  63. package/.framework/functions/cil-doc.ts +1752 -0
  64. package/.framework/functions/cil-embeddings.ts +1202 -0
  65. package/.framework/functions/cil-graph.ts +585 -0
  66. package/.framework/functions/cil-ingest.ts +2416 -0
  67. package/.framework/functions/cil-pipeline.ts +318 -0
  68. package/.framework/functions/cil-project.ts +499 -0
  69. package/.framework/functions/cil-validate.ts +469 -0
  70. package/.framework/functions/debug-auth.ts +73 -53
  71. package/.framework/functions/deliveries.ts +117 -0
  72. package/.framework/functions/embeddings.ts +528 -516
  73. package/.framework/functions/eval-harness.ts +158 -106
  74. package/.framework/functions/integration-outbound.ts +311 -0
  75. package/.framework/functions/integration-routes.ts +240 -466
  76. package/.framework/functions/integrations.ts +132 -140
  77. package/.framework/functions/invites.ts +401 -201
  78. package/.framework/functions/item-progress.ts +113 -53
  79. package/.framework/functions/kb.ts +28 -0
  80. package/.framework/functions/logs.ts +239 -222
  81. package/.framework/functions/observability.ts +308 -259
  82. package/.framework/functions/pipeline-executions.ts +179 -235
  83. package/.framework/functions/pipelines.ts +163 -205
  84. package/.framework/functions/prompt-configs.ts +109 -156
  85. package/.framework/functions/roles.ts +97 -147
  86. package/.framework/functions/system-cron.ts +132 -218
  87. package/.framework/functions/system.ts +112 -52
  88. package/.framework/functions/tests.ts +32 -28
  89. package/.framework/functions/timers.ts +162 -210
  90. package/.framework/functions/triggers.ts +282 -346
  91. package/.framework/functions/types.ts +283 -400
  92. package/.framework/migrations/001_core_schema.sql +630 -0
  93. package/.framework/migrations/002_core_rls_and_functions.sql +532 -0
  94. package/.framework/migrations/{003_system_data.sql → 003_core_system_data.sql} +26 -153
  95. package/.framework/migrations/004_core_rpc_and_broker.sql +421 -0
  96. package/.framework/migrations/005_core_observability.sql +598 -0
  97. package/.framework/migrations/006_security_hardening_rls.sql +97 -0
  98. package/.framework/migrations/007_kb_article_list.sql +237 -0
  99. package/.framework/migrations/008_items_target.sql +8 -0
  100. package/.framework/migrations/009_roles_slug_unique.sql +11 -0
  101. package/.framework/public/spine.config.json +91 -0
  102. package/.framework/scripts/app-install-cli.ts +112 -98
  103. package/.framework/src/App.tsx +67 -20
  104. package/.framework/src/apps/admin/index.tsx +97 -27
  105. package/.framework/src/components/AppWrapper.tsx +50 -11
  106. package/.framework/src/components/CustomAppLoader.tsx +131 -22
  107. package/.framework/src/components/admin/AdminListPage.tsx +75 -8
  108. package/.framework/src/components/admin/AdminSidebar.tsx +148 -36
  109. package/.framework/src/components/admin/AdminStatsCard.tsx +48 -29
  110. package/.framework/src/components/admin/PageInstructions.tsx +49 -0
  111. package/.framework/src/components/admin/SortableTableHeader.tsx +49 -2
  112. package/.framework/src/components/app-shell/GenericAppShell.tsx +69 -11
  113. package/.framework/src/components/app-shell/GenericDetailPage.tsx +55 -10
  114. package/.framework/src/components/app-shell/GenericListPage.tsx +76 -9
  115. package/.framework/src/components/app-sidebar.tsx +50 -3
  116. package/.framework/src/components/auth/ProtectedRoute.tsx +53 -45
  117. package/.framework/src/components/kb/KBArticleEditor.tsx +409 -0
  118. package/.framework/src/components/kb/KBArticleList.tsx +557 -0
  119. package/.framework/src/components/layout/AppShell.tsx +54 -16
  120. package/.framework/src/components/layout/Header.tsx +50 -38
  121. package/.framework/src/components/layout/Layout.tsx +48 -32
  122. package/.framework/src/components/layout/Sidebar.tsx +167 -16
  123. package/.framework/src/components/runtime/DataDetailHeader.tsx +33 -1
  124. package/.framework/src/components/runtime/DataDetailPage.tsx +289 -4
  125. package/.framework/src/components/runtime/DataFilters.tsx +78 -1
  126. package/.framework/src/components/runtime/DataHeader.tsx +32 -29
  127. package/.framework/src/components/runtime/DataListPage.tsx +161 -2
  128. package/.framework/src/components/runtime/DataStats.tsx +48 -1
  129. package/.framework/src/components/runtime/DataTable.tsx +153 -1
  130. package/.framework/src/components/runtime/SchemaDetailForm.tsx +77 -46
  131. package/.framework/src/components/runtime/index.ts +16 -9
  132. package/.framework/src/components/search-form.tsx +33 -1
  133. package/.framework/src/components/shared/AgentView.tsx +48 -51
  134. package/.framework/src/components/shared/FieldRenderer.tsx +84 -67
  135. package/.framework/src/components/shared/InviteManager.tsx +113 -52
  136. package/.framework/src/components/shared/MemberList.tsx +182 -0
  137. package/.framework/src/components/shared/SchemaFields.tsx +96 -78
  138. package/.framework/src/components/ui/DataTable.tsx +86 -56
  139. package/.framework/src/components/ui/Form.tsx +188 -109
  140. package/.framework/src/components/ui/ItemCard.tsx +86 -58
  141. package/.framework/src/components/ui/ItemListView.tsx +88 -61
  142. package/.framework/src/components/ui/LoadingSpinner.tsx +52 -27
  143. package/.framework/src/components/ui/Modal.tsx +81 -4
  144. package/.framework/src/components/ui/RichTextEditor.tsx +101 -9
  145. package/.framework/src/components/ui/accordion.tsx +97 -5
  146. package/.framework/src/components/ui/alert-dialog.tsx +225 -13
  147. package/.framework/src/components/ui/alert.tsx +113 -6
  148. package/.framework/src/components/ui/aspect-ratio.tsx +49 -2
  149. package/.framework/src/components/ui/avatar.tsx +129 -7
  150. package/.framework/src/components/ui/badge.tsx +65 -3
  151. package/.framework/src/components/ui/breadcrumb.tsx +145 -8
  152. package/.framework/src/components/ui/button-group.tsx +81 -4
  153. package/.framework/src/components/ui/button.tsx +49 -2
  154. package/.framework/src/components/ui/calendar.tsx +65 -3
  155. package/.framework/src/components/ui/card.tsx +145 -8
  156. package/.framework/src/components/ui/carousel.tsx +129 -7
  157. package/.framework/src/components/ui/chart.tsx +161 -10
  158. package/.framework/src/components/ui/checkbox.tsx +49 -2
  159. package/.framework/src/components/ui/collapsible.tsx +81 -5
  160. package/.framework/src/components/ui/combobox.tsx +305 -20
  161. package/.framework/src/components/ui/command.tsx +177 -11
  162. package/.framework/src/components/ui/context-menu.tsx +273 -17
  163. package/.framework/src/components/ui/dialog.tsx +209 -27
  164. package/.framework/src/components/ui/direction.tsx +64 -4
  165. package/.framework/src/components/ui/drawer.tsx +193 -12
  166. package/.framework/src/components/ui/dropdown-menu.tsx +273 -18
  167. package/.framework/src/components/ui/empty.tsx +145 -9
  168. package/.framework/src/components/ui/field.tsx +209 -14
  169. package/.framework/src/components/ui/hover-card.tsx +81 -4
  170. package/.framework/src/components/ui/input-group.tsx +162 -10
  171. package/.framework/src/components/ui/input-otp.tsx +98 -5
  172. package/.framework/src/components/ui/input.tsx +49 -2
  173. package/.framework/src/components/ui/item.tsx +225 -13
  174. package/.framework/src/components/ui/kbd.tsx +65 -3
  175. package/.framework/src/components/ui/label.tsx +49 -2
  176. package/.framework/src/components/ui/menubar.tsx +289 -17
  177. package/.framework/src/components/ui/native-select.tsx +97 -5
  178. package/.framework/src/components/ui/navigation-menu.tsx +177 -10
  179. package/.framework/src/components/ui/pagination.tsx +161 -9
  180. package/.framework/src/components/ui/popover.tsx +145 -8
  181. package/.framework/src/components/ui/progress.tsx +49 -2
  182. package/.framework/src/components/ui/radio-group.tsx +65 -3
  183. package/.framework/src/components/ui/resizable.tsx +82 -4
  184. package/.framework/src/components/ui/scroll-area.tsx +65 -3
  185. package/.framework/src/components/ui/select.tsx +193 -11
  186. package/.framework/src/components/ui/separator.tsx +49 -2
  187. package/.framework/src/components/ui/sheet.tsx +193 -11
  188. package/.framework/src/components/ui/sidebar.tsx +481 -38
  189. package/.framework/src/components/ui/skeleton.tsx +49 -2
  190. package/.framework/src/components/ui/slider.tsx +49 -2
  191. package/.framework/src/components/ui/sonner.tsx +49 -2
  192. package/.framework/src/components/ui/spinner.tsx +49 -2
  193. package/.framework/src/components/ui/switch.tsx +49 -2
  194. package/.framework/src/components/ui/table-primitives.tsx +160 -33
  195. package/.framework/src/components/ui/table.tsx +161 -9
  196. package/.framework/src/components/ui/tabs.tsx +113 -6
  197. package/.framework/src/components/ui/textarea.tsx +49 -2
  198. package/.framework/src/components/ui/toggle-group.tsx +81 -4
  199. package/.framework/src/components/ui/toggle.tsx +65 -3
  200. package/.framework/src/components/ui/tooltip.tsx +97 -5
  201. package/.framework/src/contexts/AppContext.tsx +129 -45
  202. package/.framework/src/contexts/AuthContext.tsx +173 -145
  203. package/.framework/src/hooks/use-mobile.ts +48 -2
  204. package/.framework/src/hooks/useApi.ts +208 -159
  205. package/.framework/src/hooks/useAppPath.ts +32 -23
  206. package/.framework/src/hooks/useApps.ts +51 -20
  207. package/.framework/src/hooks/useEntityList.ts +32 -78
  208. package/.framework/src/hooks/useEntityRecord.ts +35 -96
  209. package/.framework/src/hooks/useForm.ts +32 -92
  210. package/.framework/src/hooks/useListSchema.ts +49 -78
  211. package/.framework/src/hooks/useSchemaRecord.ts +114 -105
  212. package/.framework/src/lib/api.ts +192 -115
  213. package/.framework/src/lib/supabase.ts +98 -64
  214. package/.framework/src/lib/utils.ts +287 -151
  215. package/.framework/src/main.tsx +49 -3
  216. package/.framework/src/pages/DashboardPage.tsx +52 -29
  217. package/.framework/src/pages/NotFoundPage.tsx +32 -10
  218. package/.framework/src/pages/SetupPage.tsx +32 -12
  219. package/.framework/src/pages/admin/AIAgentDetailPage.tsx +119 -10
  220. package/.framework/src/pages/admin/AIAgentsPage.tsx +48 -19
  221. package/.framework/src/pages/admin/APIKeyDetailPage.tsx +187 -17
  222. package/.framework/src/pages/admin/APIKeysPage.tsx +98 -22
  223. package/.framework/src/pages/admin/AlertsConfigPage.tsx +113 -26
  224. package/.framework/src/pages/admin/AppDetailPage.tsx +125 -8
  225. package/.framework/src/pages/admin/AppsPage.tsx +49 -2
  226. package/.framework/src/pages/admin/DeliveriesPage.tsx +196 -0
  227. package/.framework/src/pages/admin/DesignedPage.tsx +32 -18
  228. package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +215 -484
  229. package/.framework/src/pages/admin/EmbeddingsPage.tsx +116 -319
  230. package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +34 -9
  231. package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +34 -9
  232. package/.framework/src/pages/admin/IntegratedDashboard.tsx +32 -16
  233. package/.framework/src/pages/admin/IntegrationDetailPage.tsx +183 -26
  234. package/.framework/src/pages/admin/IntegrationsPage.tsx +48 -19
  235. package/.framework/src/pages/admin/InvitesPage.tsx +48 -14
  236. package/.framework/src/pages/admin/LogsPage.tsx +422 -75
  237. package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +34 -9
  238. package/.framework/src/pages/admin/ObservabilityDashboard.tsx +113 -24
  239. package/.framework/src/pages/admin/PipelineDetailPage.tsx +206 -34
  240. package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +50 -17
  241. package/.framework/src/pages/admin/PipelinesPage.tsx +160 -21
  242. package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +378 -88
  243. package/.framework/src/pages/admin/PromptConfigsPage.tsx +125 -16
  244. package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +49 -10
  245. package/.framework/src/pages/admin/RoleDetailPage.tsx +130 -10
  246. package/.framework/src/pages/admin/RolesPage.tsx +171 -18
  247. package/.framework/src/pages/admin/SelectTestPage.tsx +34 -9
  248. package/.framework/src/pages/admin/ShadcnTestPage.tsx +49 -11
  249. package/.framework/src/pages/admin/SimpleDashboard.tsx +49 -10
  250. package/.framework/src/pages/admin/TestRunDetailPage.tsx +49 -4
  251. package/.framework/src/pages/admin/TestingDashboard.tsx +98 -28
  252. package/.framework/src/pages/admin/TimerDetailPage.tsx +143 -33
  253. package/.framework/src/pages/admin/TimersPage.tsx +48 -20
  254. package/.framework/src/pages/admin/TriggerDetailPage.tsx +118 -30
  255. package/.framework/src/pages/admin/TriggersPage.tsx +64 -19
  256. package/.framework/src/pages/admin/TypeDetailPage.tsx +138 -15
  257. package/.framework/src/pages/admin/TypesPage.tsx +48 -20
  258. package/.framework/src/pages/admin/cil/CILAgentPage.tsx +465 -0
  259. package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +787 -0
  260. package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +699 -0
  261. package/.framework/src/pages/admin/cil/CILFileListPage.tsx +647 -0
  262. package/.framework/src/pages/admin/cil/CILGraphPage.tsx +616 -0
  263. package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +1402 -0
  264. package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +614 -0
  265. package/.framework/src/pages/admin/cil/CILSearchPage.tsx +571 -0
  266. package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +731 -0
  267. package/.framework/src/pages/admin/kb/KBAdminPage.tsx +64 -0
  268. package/.framework/src/pages/auth/AuthConfirmPage.tsx +52 -51
  269. package/.framework/src/pages/auth/ForgotPasswordPage.tsx +31 -22
  270. package/.framework/src/pages/auth/LoginPage.tsx +50 -23
  271. package/.framework/src/pages/auth/PendingApprovalPage.tsx +31 -15
  272. package/.framework/src/pages/auth/RegisterPage.tsx +281 -317
  273. package/.framework/src/pages/spine-framework/APIPage.tsx +33 -0
  274. package/.framework/src/pages/spine-framework/CLIPage.tsx +33 -0
  275. package/.framework/src/types/auth.ts +128 -71
  276. package/.framework/src/types/types.ts +373 -157
  277. package/custom/.devin/skills/spine-workbench-discovery/SKILL.md +39 -0
  278. package/custom/.devin/skills/spine-workbench-idea/SKILL.md +36 -0
  279. package/custom/.devin/skills/spine-workbench-implement/SKILL.md +46 -0
  280. package/custom/.devin/skills/spine-workbench-initiative/SKILL.md +28 -0
  281. package/custom/.devin/skills/spine-workbench-plan/SKILL.md +38 -0
  282. package/docs/README.md +9 -130
  283. package/netlify.toml +3 -3
  284. package/package.json +13 -25
  285. package/scripts/kb-ingest-docs.ts +203 -0
  286. package/spine.config.json +65 -4
  287. package/.framework/migrations/001_schema.sql +0 -425
  288. package/.framework/migrations/002_rls_and_functions.sql +0 -763
  289. package/.framework/migrations/004_enhancements.sql +0 -43
  290. package/.framework/migrations/005_auth_user_trigger.sql +0 -105
  291. package/.framework/migrations/006_fix_current_actor_id.sql +0 -21
  292. package/.framework/migrations/016_invites.sql +0 -27
  293. package/.framework/migrations/017_fix_get_account_apps.sql +0 -78
  294. package/.framework/migrations/018_apps_required_roles.sql +0 -17
  295. package/.framework/migrations/019_triggers_unique_constraint.sql +0 -13
  296. package/.framework/migrations/020_get_account_apps_role_filter.sql +0 -117
  297. package/.framework/migrations/021_app_domains.sql +0 -112
  298. package/.framework/migrations/022_route_prefix_domain_unique.sql +0 -21
  299. package/.framework/migrations/023_match_embeddings_rpc.sql +0 -78
  300. package/.framework/migrations/024_messages_account_id.sql +0 -9
  301. package/.framework/migrations/025_retype_threads_messages.sql +0 -240
  302. package/.framework/migrations/026_fix_rls_policies.sql +0 -47
  303. package/.framework/migrations/027_embedding_lifecycle.sql +0 -176
  304. package/.framework/migrations/028_fix_message_data_permissions.sql +0 -49
  305. package/.framework/migrations/029_tighten_support_triage_prompt.sql +0 -41
  306. package/.framework/migrations/030_messages_updated_by.sql +0 -6
  307. package/.framework/migrations/031_seed_upsert_constraints.sql +0 -35
  308. package/docs/APPS.md +0 -232
  309. package/docs/ARCHITECTURE.md +0 -246
  310. package/docs/INSTALL.md +0 -155
  311. package/docs/design-schema-spec.md +0 -1837
  312. package/docs/dev-guides/01-create-an-app.md +0 -183
  313. package/docs/dev-guides/02-create-a-function.md +0 -178
  314. package/docs/dev-guides/03-create-a-component.md +0 -178
  315. package/docs/dev-guides/04-webhook-handlers.md +0 -129
  316. package/docs/dev-guides/05-testing.md +0 -168
  317. package/docs/dev-guides/README.md +0 -40
  318. package/docs/npm-packages-plan.md +0 -288
  319. package/docs/spine-core--api-reference.md +0 -822
@@ -1,59 +1,75 @@
1
- /**
2
- * @module src/lib/utils
3
- * @audience installer
4
- * @layer frontend-hook
5
- * @stability stable
6
- *
7
- * General-purpose frontend utility functions. Pure helpers only — no React,
8
- * no Supabase, no side effects. Safe to use in any component or hook.
9
- *
10
- * **Exports:** `cn`, `formatDate`, `formatTime`, `formatDateTime`,
11
- * `formatRelativeTime`, `formatFileSize`, `formatCurrency`, `formatNumber`,
12
- * `truncateText`, `generateSlug`, `capitalize`, `debounce`, `throttle`,
13
- * `isValidUrl`, `getFileExtension`, `generateId`, `deepClone`
14
- *
15
- * @seeAlso src/lib/api.ts (fetch utilities)
16
- * @seeAlso functions/_shared/schema-utils.ts (server-side field formatters
17
- * for storage-layer data; parallel set to the date/currency helpers here)
18
- */
19
1
 
20
- import { type ClassValue, clsx } from 'clsx'
21
- import { twMerge } from 'tailwind-merge'
22
2
 
23
- // ─── TAILWIND HELPERS ───────────────────────────────────────────────────────────
24
3
 
25
- /**
26
- * Merges Tailwind class strings with conflict resolution via `tailwind-merge`
27
- * and conditional class support via `clsx`. The standard utility for
28
- * composing class names in all Spine components.
29
- *
30
- * @param inputs - Any number of class values (strings, arrays, objects)
31
- * @returns Merged, deduplicated class string
32
- * @throws never
33
- * @example
34
- * ```ts
35
- * cn('px-4 py-2', isActive && 'bg-blue-500', 'px-6') // → 'py-2 bg-blue-500 px-6'
36
- * ```
37
- */
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+ // CIL[BEGIN chunk_id="utils_imports_1783712804" type="module_header" identity="imports" parent="none"]
19
+ // CIL[DOC-MACRO purpose="Import CSS class utilities"]
20
+ // CIL[DOC-RESPONSIBILITY responsibility="Provide class merging dependencies"]
21
+ // CIL[DOC-CONTEXT module="utils" layer="utility" related_files="[\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"\\\"]"]
22
+ // CIL[DOC-CONTRACT inputs="none" outputs="clsx, twMerge" errors="none" side_effects="none"]
23
+ // CIL[DOC-MICRO logic_summary="Import external CSS utility libraries" notable_decisions="[]"]
24
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
25
+ // CIL[DOC-STABILITY stability="stable"]
26
+ // CIL[DOC-AUDIENCE audience="developer"]
27
+ // CIL[DOC-VECTOR type="context" content="Layer: utility. Direct callers: 0. Direct calls: 0. Related files: custom/apps/cortex/pages/operations/OperationsDashboard.tsx, \."]
28
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
29
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
30
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
31
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
32
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
33
+ import { type ClassValue, clsx } from 'clsx'
34
+ import { twMerge } from 'tailwind-merge'
35
+ // CIL[END chunk_id="utils_imports_1783712804"]
36
+ // CIL[BEGIN chunk_id="utils_cn_1783712804" type="function" identity="cn" parent="none"]
37
+ // CIL[DOC-MACRO purpose="Merge CSS class names with Tailwind"]
38
+ // CIL[DOC-RESPONSIBILITY responsibility="Combine and deduplicate CSS classes"]
39
+ // CIL[DOC-CONTEXT module="utils" layer="utility" related_files="[\".framework/functions/_shared/schema-utils.ts\",\".framework/src/components/ui/dialog.tsx\",\".framework/functions/_shared/principal.ts\",\".framework/src/components/ui/table-primitives.tsx\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"\\\"]"]
40
+ // CIL[DOC-CONTRACT inputs="none" outputs="string" errors="none" side_effects="none"]
41
+ // CIL[DOC-MICRO logic_summary="Apply clsx then twMerge for class handling" notable_decisions="[]"]
42
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
43
+ // CIL[DOC-STABILITY stability="stable"]
44
+ // CIL[DOC-VECTOR type="context" content="Layer: utility. Direct callers: 0. Direct calls: 0. Related files: .framework/functions/_shared/schema-utils.ts, .framework/src/components/ui/dialog.tsx, .framework/functions/_shared/principal.ts, .framework/src/components/ui/table-primitives.tsx, .framework/src/pages/admin/TypeDetailPage.tsx, \."]
45
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
46
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
47
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
48
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
49
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
38
50
  export function cn(...inputs: ClassValue[]) {
39
51
  return twMerge(clsx(inputs))
40
52
  }
41
-
42
- // ─── DATE FORMATTERS ────────────────────────────────────────────────────────────
43
-
44
- /**
45
- * Formats a date as a locale date string ('Jan 15, 2024').
46
- * Returns `'N/A'` for null/undefined, `'Invalid Date'` for non-parseable input.
47
- * @param date - ISO string, Date object, null, or undefined
48
- * @param options - Optional `Intl.DateTimeFormatOptions` overrides
49
- * @throws never
50
- */
53
+ // CIL[END chunk_id="utils_cn_1783712804"]
54
+ // CIL[BEGIN chunk_id="utils_formatdate_1783712804" type="function" identity="formatDate" parent="none"]
55
+ // CIL[DOC-MACRO purpose="Format date to readable string"]
56
+ // CIL[DOC-RESPONSIBILITY responsibility="Convert date to localized format"]
57
+ // CIL[DOC-CONTEXT module="utils" layer="utility" related_files="[\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\"custom/apps/portal/pages/ContentPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/pages/admin/RolesPage.tsx\",\".framework/src/components/ui/table-primitives.tsx\",\"\\\"]"]
58
+ // CIL[DOC-CONTRACT inputs="none" outputs="string" errors="none" side_effects="none"]
59
+ // CIL[DOC-MICRO logic_summary="Handle null/invalid dates, format with options" notable_decisions="[]"]
60
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
61
+ // CIL[DOC-STABILITY stability="stable"]
62
+ // CIL[DOC-VECTOR type="context" content="Layer: utility. Direct callers: 3. Direct calls: 0. Related files: custom/apps/cortex/functions/custom_cil-embeddings.ts, custom/apps/portal/pages/ContentPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/src/pages/admin/RolesPage.tsx, .framework/src/components/ui/table-primitives.tsx, \."]
63
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 3. Total affected: 3."]
64
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
65
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
66
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
67
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
51
68
  export function formatDate(date: string | Date | null | undefined, options?: Intl.DateTimeFormatOptions) {
52
69
  if (!date) return 'N/A'
53
70
 
54
71
  const dateObj = typeof date === 'string' ? new Date(date) : date
55
72
 
56
- // Check if date is invalid
57
73
  if (!dateObj || isNaN(dateObj.getTime())) return 'Invalid Date'
58
74
 
59
75
  return dateObj.toLocaleDateString('en-US', {
@@ -63,18 +79,26 @@ export function formatDate(date: string | Date | null | undefined, options?: Int
63
79
  ...options,
64
80
  })
65
81
  }
66
-
67
- /**
68
- * Formats a date as a locale time string ('02:30 PM').
69
- * Returns `'N/A'` for null/undefined, `'Invalid Date'` for bad input.
70
- * @throws never
71
- */
82
+ // CIL[END chunk_id="utils_formatdate_1783712804"]
83
+ // CIL[BEGIN chunk_id="utils_formattime_1783712804" type="function" identity="formatTime" parent="none"]
84
+ // CIL[DOC-MACRO purpose="Format time to readable string"]
85
+ // CIL[DOC-RESPONSIBILITY responsibility="Convert time to localized format"]
86
+ // CIL[DOC-CONTEXT module="utils" layer="utility" related_files="[\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\"custom/apps/portal/pages/ContentPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/pages/admin/RolesPage.tsx\",\".framework/src/components/ui/table-primitives.tsx\",\"\\\"]"]
87
+ // CIL[DOC-CONTRACT inputs="none" outputs="string" errors="none" side_effects="none"]
88
+ // CIL[DOC-MICRO logic_summary="Handle null/invalid dates, format time with options" notable_decisions="[]"]
89
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
90
+ // CIL[DOC-STABILITY stability="stable"]
91
+ // CIL[DOC-VECTOR type="context" content="Layer: utility. Direct callers: 0. Direct calls: 0. Related files: custom/apps/cortex/functions/custom_cil-embeddings.ts, custom/apps/portal/pages/ContentPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/src/pages/admin/RolesPage.tsx, .framework/src/components/ui/table-primitives.tsx, \."]
92
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
93
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
94
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
95
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
96
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
72
97
  export function formatTime(date: string | Date | null | undefined, options?: Intl.DateTimeFormatOptions) {
73
98
  if (!date) return 'N/A'
74
99
 
75
100
  const dateObj = typeof date === 'string' ? new Date(date) : date
76
101
 
77
- // Check if date is invalid
78
102
  if (!dateObj || isNaN(dateObj.getTime())) return 'Invalid Date'
79
103
 
80
104
  return dateObj.toLocaleTimeString('en-US', {
@@ -83,18 +107,26 @@ export function formatTime(date: string | Date | null | undefined, options?: Int
83
107
  ...options,
84
108
  })
85
109
  }
86
-
87
- /**
88
- * Formats a date as a locale date+time string ('Jan 15, 2024, 02:30 PM').
89
- * Returns `'N/A'` for null/undefined, `'Invalid Date'` for bad input.
90
- * @throws never
91
- */
110
+ // CIL[END chunk_id="utils_formattime_1783712804"]
111
+ // CIL[BEGIN chunk_id="utils_formatdatetime_1783712804" type="function" identity="formatDateTime" parent="none"]
112
+ // CIL[DOC-MACRO purpose="Format date and time to readable string"]
113
+ // CIL[DOC-RESPONSIBILITY responsibility="Convert datetime to localized format"]
114
+ // CIL[DOC-CONTEXT module="utils" layer="utility" related_files="[]"]
115
+ // CIL[DOC-CONTRACT inputs="none" outputs="string" errors="none" side_effects="none"]
116
+ // CIL[DOC-MICRO logic_summary="Handle null/invalid dates, format datetime with options" notable_decisions="[]"]
117
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
118
+ // CIL[DOC-STABILITY stability="stable"]
119
+ // CIL[DOC-VECTOR type="context" content="Layer: utility. Direct callers: 0. Direct calls: 0. Related files: none."]
120
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
121
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
122
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
123
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
124
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
92
125
  export function formatDateTime(date: string | Date | null | undefined, options?: Intl.DateTimeFormatOptions) {
93
126
  if (!date) return 'N/A'
94
127
 
95
128
  const dateObj = typeof date === 'string' ? new Date(date) : date
96
129
 
97
- // Check if date is invalid
98
130
  if (!dateObj || isNaN(dateObj.getTime())) return 'Invalid Date'
99
131
 
100
132
  return dateObj.toLocaleString('en-US', {
@@ -106,20 +138,26 @@ export function formatDateTime(date: string | Date | null | undefined, options?:
106
138
  ...options,
107
139
  })
108
140
  }
109
-
110
- /**
111
- * Formats a date as a human-readable relative string
112
- * ('just now', '5 minutes ago', '3 days ago', or falls back to `formatDate`
113
- * for dates older than 7 days).
114
- * Returns `'N/A'` for null/undefined, `'Invalid Date'` for bad input.
115
- * @throws never
116
- */
141
+ // CIL[END chunk_id="utils_formatdatetime_1783712804"]
142
+ // CIL[BEGIN chunk_id="utils_formatrelativetime_1783712804" type="function" identity="formatRelativeTime" parent="none"]
143
+ // CIL[DOC-MACRO purpose="Format relative time from now"]
144
+ // CIL[DOC-RESPONSIBILITY responsibility="Convert date to human-readable relative time"]
145
+ // CIL[DOC-CONTEXT module="utils" layer="utility" related_files="[]"]
146
+ // CIL[DOC-CONTRACT inputs="none" outputs="string" errors="none" side_effects="none"]
147
+ // CIL[DOC-MICRO logic_summary="Calculate time differences and format with units" notable_decisions="[]"]
148
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
149
+ // CIL[DOC-STABILITY stability="stable"]
150
+ // CIL[DOC-VECTOR type="context" content="Layer: utility. Direct callers: 0. Direct calls: 0. Related files: none."]
151
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
152
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
153
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
154
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
155
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
117
156
  export function formatRelativeTime(date: string | Date | null | undefined) {
118
157
  if (!date) return 'N/A'
119
158
 
120
159
  const dateObj = typeof date === 'string' ? new Date(date) : date
121
160
 
122
- // Check if date is invalid
123
161
  if (isNaN(dateObj.getTime())) return 'Invalid Date'
124
162
 
125
163
  const now = new Date()
@@ -141,16 +179,21 @@ export function formatRelativeTime(date: string | Date | null | undefined) {
141
179
  return formatDate(dateObj)
142
180
  }
143
181
  }
144
-
145
- // ─── NUMBER FORMATTERS ───────────────────────────────────────────────────────────
146
-
147
- /**
148
- * Formats bytes as a human-readable size string ('1.23 MB').
149
- * Returns `'0 Bytes'` for 0.
150
- * @param bytes - Non-negative byte count
151
- * @param decimals - Decimal places (default 2)
152
- * @throws never
153
- */
182
+ // CIL[END chunk_id="utils_formatrelativetime_1783712804"]
183
+ // CIL[BEGIN chunk_id="utils_formatfilesize_1783712804" type="function" identity="formatFileSize" parent="none"]
184
+ // CIL[DOC-MACRO purpose="Format file size with appropriate units"]
185
+ // CIL[DOC-RESPONSIBILITY responsibility="Convert bytes to human-readable size"]
186
+ // CIL[DOC-CONTEXT module="utils" layer="utility" related_files="[\".framework/functions/_shared/schema-utils.ts\",\".framework/src/components/ui/dialog.tsx\",\".framework/functions/_shared/principal.ts\",\".framework/src/components/ui/table-primitives.tsx\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"\\\"]"]
187
+ // CIL[DOC-CONTRACT inputs="none" outputs="string" errors="none" side_effects="none"]
188
+ // CIL[DOC-MICRO logic_summary="Calculate appropriate unit and format with decimals" notable_decisions="[]"]
189
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
190
+ // CIL[DOC-STABILITY stability="stable"]
191
+ // CIL[DOC-VECTOR type="context" content="Layer: utility. Direct callers: 0. Direct calls: 0. Related files: .framework/functions/_shared/schema-utils.ts, .framework/src/components/ui/dialog.tsx, .framework/functions/_shared/principal.ts, .framework/src/components/ui/table-primitives.tsx, .framework/src/pages/admin/TypeDetailPage.tsx, \."]
192
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
193
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
194
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
195
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
196
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
154
197
  export function formatFileSize(bytes: number, decimals = 2) {
155
198
  if (bytes === 0) return '0 Bytes'
156
199
 
@@ -162,47 +205,79 @@ export function formatFileSize(bytes: number, decimals = 2) {
162
205
 
163
206
  return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]
164
207
  }
165
-
166
- /**
167
- * Formats a number as a locale currency string ('$1,234.56').
168
- * @param amount - Numeric value
169
- * @param currency - ISO 4217 code (default 'USD')
170
- * @param locale - BCP 47 locale tag (default 'en-US')
171
- * @throws never
172
- */
208
+ // CIL[END chunk_id="utils_formatfilesize_1783712804"]
209
+ // CIL[BEGIN chunk_id="utils_formatcurrency_1783712804" type="function" identity="formatCurrency" parent="none"]
210
+ // CIL[DOC-MACRO purpose="Format number as currency"]
211
+ // CIL[DOC-RESPONSIBILITY responsibility="Convert amount to localized currency format"]
212
+ // CIL[DOC-CONTEXT module="utils" layer="utility" related_files="[\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/pages/admin/RolesPage.tsx\",\"\\\"]"]
213
+ // CIL[DOC-CONTRACT inputs="none" outputs="string" errors="none" side_effects="none"]
214
+ // CIL[DOC-MICRO logic_summary="Use Intl.NumberFormat for currency formatting" notable_decisions="[]"]
215
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
216
+ // CIL[DOC-STABILITY stability="stable"]
217
+ // CIL[DOC-VECTOR type="context" content="Layer: utility. Direct callers: 0. Direct calls: 0. Related files: custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/src/pages/admin/RolesPage.tsx, \."]
218
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
219
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
220
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
221
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
222
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
173
223
  export function formatCurrency(amount: number, currency = 'USD', locale = 'en-US') {
174
224
  return new Intl.NumberFormat(locale, {
175
225
  style: 'currency',
176
226
  currency,
177
227
  }).format(amount)
178
228
  }
179
-
180
- /**
181
- * Formats a number using `Intl.NumberFormat` with optional format options.
182
- * @throws never
183
- */
229
+ // CIL[END chunk_id="utils_formatcurrency_1783712804"]
230
+ // CIL[BEGIN chunk_id="utils_formatnumber_1783712804" type="function" identity="formatNumber" parent="none"]
231
+ // CIL[DOC-MACRO purpose="Format number with localization"]
232
+ // CIL[DOC-RESPONSIBILITY responsibility="Convert number to localized format"]
233
+ // CIL[DOC-CONTEXT module="utils" layer="utility" related_files="[\".framework/functions/_shared/schema-utils.ts\",\".framework/src/components/ui/dialog.tsx\",\".framework/functions/_shared/principal.ts\",\".framework/src/components/ui/table-primitives.tsx\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"\\\"]"]
234
+ // CIL[DOC-CONTRACT inputs="none" outputs="string" errors="none" side_effects="none"]
235
+ // CIL[DOC-MICRO logic_summary="Use Intl.NumberFormat for number formatting" notable_decisions="[]"]
236
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
237
+ // CIL[DOC-STABILITY stability="stable"]
238
+ // CIL[DOC-VECTOR type="context" content="Layer: utility. Direct callers: 0. Direct calls: 0. Related files: .framework/functions/_shared/schema-utils.ts, .framework/src/components/ui/dialog.tsx, .framework/functions/_shared/principal.ts, .framework/src/components/ui/table-primitives.tsx, .framework/src/pages/admin/TypeDetailPage.tsx, \."]
239
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
240
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
241
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
242
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
243
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
184
244
  export function formatNumber(num: number, options?: Intl.NumberFormatOptions) {
185
245
  return new Intl.NumberFormat('en-US', options).format(num)
186
246
  }
187
-
188
- // ─── STRING UTILITIES ────────────────────────────────────────────────────────────
189
-
190
- /**
191
- * Truncates text to `maxLength` characters, appending `'...'` if truncated.
192
- * Returns the original string if it fits within `maxLength`.
193
- * @throws never
194
- */
247
+ // CIL[END chunk_id="utils_formatnumber_1783712804"]
248
+ // CIL[BEGIN chunk_id="utils_truncatetext_1783712804" type="function" identity="truncateText" parent="none"]
249
+ // CIL[DOC-MACRO purpose="Truncate text to maximum length"]
250
+ // CIL[DOC-RESPONSIBILITY responsibility="Limit text length with ellipsis"]
251
+ // CIL[DOC-CONTEXT module="utils" layer="utility" related_files="[]"]
252
+ // CIL[DOC-CONTRACT inputs="none" outputs="string" errors="none" side_effects="none"]
253
+ // CIL[DOC-MICRO logic_summary="Check length, slice if needed, add ellipsis" notable_decisions="[]"]
254
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
255
+ // CIL[DOC-STABILITY stability="stable"]
256
+ // CIL[DOC-VECTOR type="context" content="Layer: utility. Direct callers: 0. Direct calls: 0. Related files: none."]
257
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
258
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
259
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
260
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
261
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
195
262
  export function truncateText(text: string, maxLength: number) {
196
263
  if (text.length <= maxLength) return text
197
264
  return text.slice(0, maxLength) + '...'
198
265
  }
199
-
200
- /**
201
- * Converts text to a URL-friendly slug: lowercased, diacritics stripped,
202
- * spaces/underscores/hyphens collapsed to single `-`, leading/trailing
203
- * hyphens removed.
204
- * @throws never
205
- */
266
+ // CIL[END chunk_id="utils_truncatetext_1783712804"]
267
+ // CIL[BEGIN chunk_id="utils_generateslug_1783712804" type="function" identity="generateSlug" parent="none"]
268
+ // CIL[DOC-MACRO purpose="Convert text to URL-friendly slug"]
269
+ // CIL[DOC-RESPONSIBILITY responsibility="Create slug from text string"]
270
+ // CIL[DOC-CONTEXT module="utils" layer="utility" related_files="[\".framework/functions/_shared/schema-utils.ts\",\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\"custom/apps/portal/pages/ContentPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/components/ui/table-primitives.tsx\"]"]
271
+ // CIL[DOC-CONTRACT inputs="none" outputs="string" errors="none" side_effects="none"]
272
+ // CIL[DOC-MICRO logic_summary="Lowercase, remove special chars, replace spaces, trim" notable_decisions="[]"]
273
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
274
+ // CIL[DOC-STABILITY stability="stable"]
275
+ // CIL[DOC-VECTOR type="context" content="Layer: utility. Direct callers: 0. Direct calls: 0. Related files: .framework/functions/_shared/schema-utils.ts, custom/apps/cortex/functions/custom_cil-embeddings.ts, custom/apps/portal/pages/ContentPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/src/components/ui/table-primitives.tsx."]
276
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
277
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
278
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
279
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
280
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
206
281
  export function generateSlug(text: string) {
207
282
  return text
208
283
  .toLowerCase()
@@ -210,25 +285,39 @@ export function generateSlug(text: string) {
210
285
  .replace(/[\s_-]+/g, '-')
211
286
  .replace(/^-+|-+$/g, '')
212
287
  }
213
-
214
- /** Capitalises the first character of a string. @throws never */
288
+ // CIL[END chunk_id="utils_generateslug_1783712804"]
289
+ // CIL[BEGIN chunk_id="utils_capitalize_1783712804" type="function" identity="capitalize" parent="none"]
290
+ // CIL[DOC-MACRO purpose="Capitalize first letter of text"]
291
+ // CIL[DOC-RESPONSIBILITY responsibility="Format text with proper capitalization"]
292
+ // CIL[DOC-CONTEXT module="utils" layer="utility" related_files="[\".framework/functions/_shared/schema-utils.ts\",\".framework/src/components/ui/table-primitives.tsx\"]"]
293
+ // CIL[DOC-CONTRACT inputs="none" outputs="string" errors="none" side_effects="none"]
294
+ // CIL[DOC-MICRO logic_summary="Get first char, uppercase, concat with rest" notable_decisions="[]"]
295
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
296
+ // CIL[DOC-STABILITY stability="stable"]
297
+ // CIL[DOC-VECTOR type="context" content="Layer: utility. Direct callers: 0. Direct calls: 0. Related files: .framework/functions/_shared/schema-utils.ts, .framework/src/components/ui/table-primitives.tsx."]
298
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
299
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
300
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
301
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
302
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
215
303
  export function capitalize(text: string) {
216
304
  return text.charAt(0).toUpperCase() + text.slice(1)
217
305
  }
218
-
219
- // ─── TIMING UTILITIES ────────────────────────────────────────────────────────────
220
-
221
- /**
222
- * Returns a debounced wrapper that delays invoking `func` until `wait` ms
223
- * after the last call. Resets the timer on each call.
224
- * @param func - The function to debounce
225
- * @param wait - Delay in milliseconds
226
- * @throws never (the wrapper itself never throws; `func` may throw)
227
- * @example
228
- * ```ts
229
- * const search = debounce((q: string) => fetchResults(q), 300)
230
- * ```
231
- */
306
+ // CIL[END chunk_id="utils_capitalize_1783712804"]
307
+ // CIL[BEGIN chunk_id="utils_debounce_1783712804" type="function" identity="debounce" parent="none"]
308
+ // CIL[DOC-MACRO purpose="Debounce function calls"]
309
+ // CIL[DOC-RESPONSIBILITY responsibility="Delay function execution until wait period ends"]
310
+ // CIL[DOC-CONTEXT module="utils" layer="utility" related_files="[\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\".framework/functions/_shared/principal.ts\",\".framework/functions/_shared/schema-utils.ts\",\"\\\"]"]
311
+ // CIL[DOC-CONTRACT inputs="none" outputs="(...args: Parameters<T>) => void" errors="none" side_effects="timer_management"]
312
+ // CIL[DOC-MICRO logic_summary="Clear previous timeout, set new timeout for function" notable_decisions="[]"]
313
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
314
+ // CIL[DOC-STABILITY stability="stable"]
315
+ // CIL[DOC-VECTOR type="context" content="Layer: utility. Direct callers: 0. Direct calls: 0. Related files: custom/apps/cortex/functions/custom_cil-embeddings.ts, .framework/functions/_shared/principal.ts, .framework/functions/_shared/schema-utils.ts, \."]
316
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
317
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
318
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
319
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
320
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
232
321
  export function debounce<T extends (...args: any[]) => any>(
233
322
  func: T,
234
323
  wait: number
@@ -239,14 +328,21 @@ export function debounce<T extends (...args: any[]) => any>(
239
328
  timeout = setTimeout(() => func(...args), wait)
240
329
  }
241
330
  }
242
-
243
- /**
244
- * Returns a throttled wrapper that invokes `func` at most once per `limit` ms.
245
- * Subsequent calls within the window are dropped.
246
- * @param func - The function to throttle
247
- * @param limit - Throttle window in milliseconds
248
- * @throws never
249
- */
331
+ // CIL[END chunk_id="utils_debounce_1783712804"]
332
+ // CIL[BEGIN chunk_id="utils_throttle_1783712804" type="function" identity="throttle" parent="none"]
333
+ // CIL[DOC-MACRO purpose="Throttle function calls"]
334
+ // CIL[DOC-RESPONSIBILITY responsibility="Limit function execution frequency"]
335
+ // CIL[DOC-CONTEXT module="utils" layer="utility" related_files="[\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\".framework/functions/_shared/principal.ts\",\".framework/functions/_shared/schema-utils.ts\",\"\\\"]"]
336
+ // CIL[DOC-CONTRACT inputs="none" outputs="(...args: Parameters<T>) => void" errors="none" side_effects="timer_management"]
337
+ // CIL[DOC-MICRO logic_summary="Execute immediately, then ignore until limit expires" notable_decisions="[]"]
338
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
339
+ // CIL[DOC-STABILITY stability="stable"]
340
+ // CIL[DOC-VECTOR type="context" content="Layer: utility. Direct callers: 0. Direct calls: 0. Related files: custom/apps/cortex/functions/custom_cil-embeddings.ts, .framework/functions/_shared/principal.ts, .framework/functions/_shared/schema-utils.ts, \."]
341
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
342
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
343
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
344
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
345
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
250
346
  export function throttle<T extends (...args: any[]) => any>(
251
347
  func: T,
252
348
  limit: number
@@ -260,10 +356,21 @@ export function throttle<T extends (...args: any[]) => any>(
260
356
  }
261
357
  }
262
358
  }
263
-
264
- // ─── VALIDATION & FILE UTILITIES ────────────────────────────────────────────────────
265
-
266
- /** Returns true if `url` is a valid absolute URL (any protocol). @throws never */
359
+ // CIL[END chunk_id="utils_throttle_1783712804"]
360
+ // CIL[BEGIN chunk_id="utils_isvalidurl_1783712804" type="function" identity="isValidUrl" parent="none"]
361
+ // CIL[DOC-MACRO purpose="Validate URL string format"]
362
+ // CIL[DOC-RESPONSIBILITY responsibility="Check if string is valid URL"]
363
+ // CIL[DOC-CONTEXT module="utils" layer="utility" related_files="[\".framework/functions/_shared/schema-utils.ts\",\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\".framework/src/pages/admin/RolesPage.tsx\"]"]
364
+ // CIL[DOC-CONTRACT inputs="none" outputs="boolean" errors="none" side_effects="none"]
365
+ // CIL[DOC-MICRO logic_summary="Try URL constructor, return true/false based on success" notable_decisions="[]"]
366
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
367
+ // CIL[DOC-STABILITY stability="stable"]
368
+ // CIL[DOC-VECTOR type="context" content="Layer: utility. Direct callers: 0. Direct calls: 0. Related files: .framework/functions/_shared/schema-utils.ts, custom/apps/cortex/functions/custom_cil-embeddings.ts, .framework/src/pages/admin/RolesPage.tsx."]
369
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
370
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
371
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
372
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
373
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
267
374
  export function isValidUrl(url: string) {
268
375
  try {
269
376
  new URL(url)
@@ -272,17 +379,39 @@ export function isValidUrl(url: string) {
272
379
  return false
273
380
  }
274
381
  }
275
-
276
- /**
277
- * Extracts the file extension from a filename. Returns an empty string if
278
- * there is no extension. Works correctly for dotfiles (e.g. `.gitignore` → `''`).
279
- * @throws never
280
- */
382
+ // CIL[END chunk_id="utils_isvalidurl_1783712804"]
383
+ // CIL[BEGIN chunk_id="utils_getfileextension_1783712804" type="function" identity="getFileExtension" parent="none"]
384
+ // CIL[DOC-MACRO purpose="Extract file extension from filename"]
385
+ // CIL[DOC-RESPONSIBILITY responsibility="Parse filename to get extension"]
386
+ // CIL[DOC-CONTEXT module="utils" layer="utility" related_files="[\"\\\"]"]
387
+ // CIL[DOC-CONTRACT inputs="none" outputs="string" errors="none" side_effects="none"]
388
+ // CIL[DOC-MICRO logic_summary="Use lastIndexOf and bit tricks for extraction" notable_decisions="[]"]
389
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
390
+ // CIL[DOC-STABILITY stability="stable"]
391
+ // CIL[DOC-VECTOR type="context" content="Layer: utility. Direct callers: 0. Direct calls: 0. Related files: \."]
392
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
393
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
394
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
395
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
396
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
281
397
  export function getFileExtension(filename: string) {
282
398
  return filename.slice((filename.lastIndexOf('.') - 1 >>> 0) + 2)
283
399
  }
284
-
285
- /** Generates a random alphanumeric ID of the given length (default 8). @throws never */
400
+ // CIL[END chunk_id="utils_getfileextension_1783712804"]
401
+ // CIL[BEGIN chunk_id="utils_generateid_1783712804" type="function" identity="generateId" parent="none"]
402
+ // CIL[DOC-MACRO purpose="Generate random alphanumeric ID"]
403
+ // CIL[DOC-RESPONSIBILITY responsibility="Create unique identifier string"]
404
+ // CIL[DOC-CONTEXT module="utils" layer="utility" related_files="[\".framework/functions/_shared/schema-utils.ts\",\".framework/src/pages/admin/RolesPage.tsx\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"custom/apps/cortex/functions/custom_cil-embeddings.ts\"]"]
405
+ // CIL[DOC-CONTRACT inputs="none" outputs="string" errors="none" side_effects="none"]
406
+ // CIL[DOC-MICRO logic_summary="Loop and append random chars from charset" notable_decisions="[]"]
407
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
408
+ // CIL[DOC-STABILITY stability="stable"]
409
+ // CIL[DOC-VECTOR type="context" content="Layer: utility. Direct callers: 0. Direct calls: 0. Related files: .framework/functions/_shared/schema-utils.ts, .framework/src/pages/admin/RolesPage.tsx, .framework/src/pages/admin/TypeDetailPage.tsx, custom/apps/cortex/functions/custom_cil-embeddings.ts."]
410
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
411
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
412
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
413
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
414
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
286
415
  export function generateId(length = 8) {
287
416
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
288
417
  let result = ''
@@ -291,15 +420,21 @@ export function generateId(length = 8) {
291
420
  }
292
421
  return result
293
422
  }
294
-
295
- // ─── OBJECT UTILITIES ─────────────────────────────────────────────────────────────
296
-
297
- /**
298
- * Recursively deep-clones an object, array, or Date. Primitives and null
299
- * are returned by value. Does not handle Maps, Sets, or class instances
300
- * with custom prototypes.
301
- * @throws never
302
- */
423
+ // CIL[END chunk_id="utils_generateid_1783712804"]
424
+ // CIL[BEGIN chunk_id="utils_deepclone_1783712804" type="function" identity="deepClone" parent="none"]
425
+ // CIL[DOC-MACRO purpose="Deep clone object recursively"]
426
+ // CIL[DOC-RESPONSIBILITY responsibility="Create independent copy of complex objects"]
427
+ // CIL[DOC-CONTEXT module="utils" layer="utility" related_files="[]"]
428
+ // CIL[DOC-CONTRACT inputs="none" outputs="T" errors="none" side_effects="none"]
429
+ // CIL[DOC-MICRO logic_summary="Handle primitives, dates, arrays, objects recursively" notable_decisions="[]"]
430
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
431
+ // CIL[DOC-STABILITY stability="stable"]
432
+ // CIL[DOC-VECTOR type="context" content="Layer: utility. Direct callers: 0. Direct calls: 0. Related files: none."]
433
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
434
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
435
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
436
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
437
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
303
438
  export function deepClone<T>(obj: T): T {
304
439
  if (obj === null || typeof obj !== 'object') return obj
305
440
  if (obj instanceof Date) return new Date(obj.getTime()) as unknown as T
@@ -315,3 +450,4 @@ export function deepClone<T>(obj: T): T {
315
450
  }
316
451
  return obj
317
452
  }
453
+ // CIL[END chunk_id="utils_deepclone_1783712804"]