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.
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 +179 -69
  6. package/.framework/cli/commands/generate.ts +83 -143
  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} +158 -56
  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 +224 -335
  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 +188 -16
  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 +685 -537
  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 +187 -144
  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 +195 -116
  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 +5 -2
  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,50 +1,43 @@
1
- /**
2
- * @module ai-interactions
3
- * @audience both
4
- * @layer api-handler
5
- * @stability stable
6
- *
7
- * Feedback capture and training data API for the AI-first support loop.
8
- * Every AI↔human exchange produces a structured interaction record so the
9
- * platform can measure loop health, drive KB creation, and accumulate a
10
- * proprietary training dataset.
11
- *
12
- * **Routed by:** `GET/POST/PATCH /.netlify/functions/ai-interactions`
13
- *
14
- * **Actions:**
15
- * | method | ?action | handler |
16
- * |--------|--------------------------|--------------------------|
17
- * | POST | submit_feedback | submitFeedback |
18
- * | POST | create_interaction | createInteraction |
19
- * | PATCH | update_interaction | updateInteraction |
20
- * | GET | list | list |
21
- * | GET | metrics | metrics |
22
- *
23
- * INVARIANT: All writes go through admin-data — no direct DB writes here.
24
- * INVARIANT: `submit_feedback` not_helpful triggers ticket escalation
25
- * by updating ticket status to human_assigned.
26
- *
27
- * @seeAlso agent-runner.ts (populates messages.data.retrieved_sources)
28
- * @seeAlso custom/portal/hooks/useTickets.ts (calls submit_feedback)
29
- * @seeAlso custom/cortex/functions/custom_case_analysis.ts (calls create_interaction)
30
- */
31
1
 
2
+
3
+
4
+
5
+
6
+ // CIL[BEGIN chunk_id="ai-interactions_module_header_1784019432" type="module_header" identity="imports" parent="none"]
7
+ // CIL[DOC-MACRO purpose="Import dependencies for AI interaction management"]
8
+ // CIL[DOC-RESPONSIBILITY responsibility="Provide middleware, database, type resolution, CRUD, and audit logging"]
9
+ // CIL[DOC-CONTEXT module="ai-interactions" layer="api-handler" related_files="[\".framework/src/pages/admin/TypeDetailPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/functions/_shared/schema-utils.ts\",\".framework/functions/_shared/principal.ts\",\"custom/apps/portal/pages/ContentPage.tsx\",\"\\\"]"]
10
+ // CIL[DOC-CONTRACT inputs="none" outputs="imported_modules" errors="none" side_effects="none"]
11
+ // CIL[DOC-MICRO logic_summary="Imports required modules for AI feedback and interaction tracking" notable_decisions="[]"]
12
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
13
+ // CIL[DOC-STABILITY stability="stable"]
14
+ // CIL[DOC-AUDIENCE audience="developer"]
15
+ // CIL[DOC-VECTOR type="context" content="Layer: api-handler. Direct callers: 0. Direct calls: 0. Related files: .framework/src/pages/admin/TypeDetailPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/functions/_shared/schema-utils.ts, .framework/functions/_shared/principal.ts, custom/apps/portal/pages/ContentPage.tsx, \."]
16
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
17
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
18
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
19
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
20
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
32
21
  import { createHandler } from './_shared/middleware'
33
22
  import { adminDb } from './_shared/db'
34
23
  import { resolveTypeId } from './_shared/resolve-ids'
35
24
  import { create, update } from './admin-data'
36
25
  import { emitLog } from './_shared/audit'
37
-
38
- // ─── SUBMIT FEEDBACK ─────────────────────────────────────────────────────────
39
- /**
40
- * Records customer helpful / not_helpful feedback on an AI message.
41
- *
42
- * - Stamps messages.data.feedback
43
- * - If not_helpful: updates ticket to human_assigned + stamps escalation reason
44
- * - Updates the matching ai_feedback_record if one exists for this message
45
- *
46
- * Body: message_id (required), ticket_id (required), feedback ('helpful' | 'not_helpful')
47
- */
26
+ // CIL[END chunk_id="ai-interactions_module_header_1784019432"]
27
+ // CIL[BEGIN chunk_id="ai-interactions_submitfeedback_1784019432" type="function" identity="submitFeedback" parent="none"]
28
+ // CIL[DOC-MACRO purpose="Record customer feedback on AI messages"]
29
+ // CIL[DOC-RESPONSIBILITY responsibility="Stamp feedback, escalate tickets, update interaction records"]
30
+ // CIL[DOC-CONTEXT module="ai-interactions" layer="api-handler" related_files="[\".framework/functions/_shared/schema-utils.ts\",\".framework/src/components/ui/dialog.tsx\",\"custom/apps/portal/pages/ContentPage.tsx\",\".framework/functions/_shared/principal.ts\",\".framework/migrations/015_simplify_apps_table.sql\",\"\\\"]"]
31
+ // CIL[DOC-CONTRACT inputs="none" outputs="feedback_confirmation" errors="message_id_required,ticket_id_required,invalid_feedback" side_effects="database_updates,ticket_escalation,audit_logging"]
32
+ // CIL[DOC-MICRO logic_summary="Stamps feedback on message, escalates not_helpful to human, updates interaction record" notable_decisions="[]"]
33
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
34
+ // CIL[DOC-STABILITY stability="stable"]
35
+ // CIL[DOC-VECTOR type="context" content="Layer: api-handler. Direct callers: 0. Direct calls: 0. Related files: .framework/functions/_shared/schema-utils.ts, .framework/src/components/ui/dialog.tsx, custom/apps/portal/pages/ContentPage.tsx, .framework/functions/_shared/principal.ts, .framework/migrations/015_simplify_apps_table.sql, \."]
36
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
37
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
38
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
39
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
40
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
48
41
  export const submitFeedback = createHandler(async (ctx, body) => {
49
42
  const { message_id, ticket_id, feedback } = body || {}
50
43
  if (!message_id) throw new Error('message_id is required')
@@ -53,7 +46,6 @@ export const submitFeedback = createHandler(async (ctx, body) => {
53
46
  throw new Error('feedback must be "helpful" or "not_helpful"')
54
47
  }
55
48
 
56
- // Stamp feedback on the message — load existing data to merge safely
57
49
  const { data: msg } = await adminDb
58
50
  .from('messages').select('data').eq('id', message_id).single()
59
51
  if (msg) {
@@ -63,7 +55,6 @@ export const submitFeedback = createHandler(async (ctx, body) => {
63
55
  .eq('id', message_id)
64
56
  }
65
57
 
66
- // If not_helpful: escalate the ticket to human support
67
58
  if (feedback === 'not_helpful' && ticket_id) {
68
59
  const { data: ticket } = await adminDb
69
60
  .from('items').select('status, data').eq('id', ticket_id).single()
@@ -79,7 +70,6 @@ export const submitFeedback = createHandler(async (ctx, body) => {
79
70
  }
80
71
  }
81
72
 
82
- // Best-effort: update matching ai_feedback_record customer_feedback field
83
73
  const { data: interactionRows } = await adminDb
84
74
  .from('items')
85
75
  .select('id, data')
@@ -100,31 +90,39 @@ export const submitFeedback = createHandler(async (ctx, body) => {
100
90
 
101
91
  return { message_id, ticket_id, feedback, escalated: feedback === 'not_helpful' }
102
92
  })
103
-
104
- // ─── CREATE INTERACTION ───────────────────────────────────────────────────────
105
- /**
106
- * Creates an ai_feedback_record item capturing a full AI↔human exchange.
107
- * Called by the capture_ai_interaction pipeline after each agent message.
108
- *
109
- * Body: thread_id, ai_message_id, retrieved_sources, ai_confidence,
110
- * retrieval_confidence, kb_candidate (optional)
111
- */
93
+ // CIL[END chunk_id="ai-interactions_submitfeedback_1784019432"]
94
+ // CIL[BEGIN chunk_id="ai-interactions_createinteraction_1784019432" type="function" identity="createInteraction" parent="none"]
95
+ // CIL[DOC-MACRO purpose="Create AI interaction feedback record"]
96
+ // CIL[DOC-RESPONSIBILITY responsibility="Create structured record of AI-human exchange"]
97
+ // CIL[DOC-CONTEXT module="ai-interactions" layer="api-handler" related_files="[\".framework/src/pages/admin/TypeDetailPage.tsx\",\".framework/src/components/ui/dialog.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/functions/_shared/schema-utils.ts\",\"\\\"]"]
98
+ // CIL[DOC-CONTRACT inputs="none" outputs="created_record_or_skip" errors="thread_or_message_required,type_not_found" side_effects="database_record_creation,type_resolution"]
99
+ // CIL[DOC-MICRO logic_summary="Resolves type, creates record with interaction metadata, handles missing type gracefully" notable_decisions="[]"]
100
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="external_symbols_unknown"]
101
+ // CIL[DOC-STABILITY stability="stable"]
102
+ // CIL[DOC-VECTOR type="context" content="Layer: api-handler. Direct callers: 0. Direct calls: 0. Related files: .framework/src/pages/admin/TypeDetailPage.tsx, .framework/src/components/ui/dialog.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/functions/_shared/schema-utils.ts, \."]
103
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
104
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
105
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
106
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
107
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
112
108
  export const createInteraction = createHandler(async (ctx, body) => {
113
109
  const {
114
110
  thread_id, ai_message_id, retrieved_sources = [],
115
- ai_confidence, retrieval_confidence, kb_candidate
111
+ per_source_feedback = [],
112
+ ai_confidence, retrieval_confidence, kb_candidate,
113
+ answer_quality, assistance_outcome,
114
+ eval_case_id, cil_learning_proposal_id,
115
+ review_notes, reviewed_by, reviewed_at
116
116
  } = body || {}
117
117
 
118
118
  if (!thread_id && !ai_message_id) {
119
119
  throw new Error('thread_id or ai_message_id is required')
120
120
  }
121
121
 
122
- // Resolve the ai_feedback_record type — it lives in the cortex/portal app seeds
123
122
  let typeId: string | null = null
124
123
  try {
125
124
  typeId = await resolveTypeId('item', 'ai_feedback_record')
126
125
  } catch {
127
- // Type not yet seeded — skip creation gracefully
128
126
  return { skipped: true, reason: 'ai_feedback_record type not found' }
129
127
  }
130
128
  if (!typeId) return { skipped: true, reason: 'ai_feedback_record type not found' }
@@ -135,40 +133,54 @@ export const createInteraction = createHandler(async (ctx, body) => {
135
133
  title: `AI Interaction — ${new Date().toISOString().slice(0, 10)}`,
136
134
  status: 'active',
137
135
  data: {
138
- thread_id: thread_id || null,
139
- ai_message_id: ai_message_id || null,
140
- human_message_id: null,
141
- retrieved_sources: retrieved_sources,
142
- ai_confidence: ai_confidence ?? null,
143
- retrieval_confidence: retrieval_confidence ?? null,
144
- human_edits_made: false,
145
- customer_feedback: null,
146
- kb_candidate: kb_candidate ?? null,
147
- kb_article_id: null,
148
- reuse_count: 0,
136
+ thread_id: thread_id || null,
137
+ ai_message_id: ai_message_id || null,
138
+ human_message_id: null,
139
+ retrieved_sources: retrieved_sources,
140
+ per_source_feedback: per_source_feedback,
141
+ ai_confidence: ai_confidence ?? null,
142
+ retrieval_confidence: retrieval_confidence ?? null,
143
+ human_edits_made: false,
144
+ customer_feedback: null,
145
+ answer_quality: answer_quality ?? null,
146
+ assistance_outcome: assistance_outcome ?? null,
147
+ kb_candidate: kb_candidate ?? null,
148
+ kb_article_id: null,
149
+ eval_case_id: eval_case_id ?? null,
150
+ cil_learning_proposal_id: cil_learning_proposal_id ?? null,
151
+ review_notes: review_notes ?? null,
152
+ reviewed_by: reviewed_by ?? null,
153
+ reviewed_at: reviewed_at ?? null,
154
+ reuse_count: 0,
149
155
  },
150
156
  })
151
157
 
152
158
  return record
153
159
  })
154
-
155
- // ─── UPDATE INTERACTION ───────────────────────────────────────────────────────
156
- /**
157
- * Patches an existing ai_feedback_record.
158
- * Used to:
159
- * - Link the KB article once a feedback record's question is promoted
160
- * - Increment reuse_count when a similar question is AI-answered
161
- * - Record human_message_id and human_edits_made after resolution
162
- *
163
- * Body: id (required), plus any of: kb_article_id, reuse_count,
164
- * human_message_id, human_edits_made, customer_feedback
165
- */
160
+ // CIL[END chunk_id="ai-interactions_createinteraction_1784019432"]
161
+ // CIL[BEGIN chunk_id="ai-interactions_updateinteraction_1784019432" type="function" identity="updateInteraction" parent="none"]
162
+ // CIL[DOC-MACRO purpose="Update AI interaction feedback record"]
163
+ // CIL[DOC-RESPONSIBILITY responsibility="Patch allowed fields on interaction record"]
164
+ // CIL[DOC-CONTEXT module="ai-interactions" layer="api-handler" related_files="[\".framework/src/pages/admin/TypeDetailPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/functions/_shared/schema-utils.ts\",\"\\\"]"]
165
+ // CIL[DOC-CONTRACT inputs="none" outputs="updated_record" errors="id_required,no_updatable_fields,record_not_found" side_effects="database_update,data_merging"]
166
+ // CIL[DOC-MICRO logic_summary="Filters allowed fields, merges with existing data, updates record" notable_decisions="[]"]
167
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
168
+ // CIL[DOC-STABILITY stability="stable"]
169
+ // CIL[DOC-VECTOR type="context" content="Layer: api-handler. Direct callers: 0. Direct calls: 0. Related files: .framework/src/pages/admin/TypeDetailPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/functions/_shared/schema-utils.ts, \."]
170
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
171
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
172
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
173
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
174
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
166
175
  export const updateInteraction = createHandler(async (ctx, body) => {
167
176
  const { id, ...fields } = body || {}
168
177
  if (!id) throw new Error('id is required')
169
178
 
170
179
  const allowed = ['kb_article_id', 'human_message_id', 'human_edits_made',
171
- 'customer_feedback', 'kb_candidate', 'reuse_count']
180
+ 'customer_feedback', 'kb_candidate', 'reuse_count',
181
+ 'per_source_feedback', 'answer_quality', 'assistance_outcome',
182
+ 'eval_case_id', 'cil_learning_proposal_id',
183
+ 'review_notes', 'reviewed_by', 'reviewed_at']
172
184
  const patch: Record<string, any> = {}
173
185
  for (const key of allowed) {
174
186
  if (fields[key] !== undefined) patch[key] = fields[key]
@@ -176,7 +188,6 @@ export const updateInteraction = createHandler(async (ctx, body) => {
176
188
 
177
189
  if (!Object.keys(patch).length) throw new Error('No updatable fields provided')
178
190
 
179
- // Load existing data then merge
180
191
  const { data: existing } = await adminDb
181
192
  .from('items').select('data').eq('id', id).single()
182
193
  if (!existing) throw new Error('Interaction record not found')
@@ -186,12 +197,76 @@ export const updateInteraction = createHandler(async (ctx, body) => {
186
197
  { data: { ...(existing.data || {}), ...patch } }
187
198
  )
188
199
  })
200
+ // CIL[END chunk_id="ai-interactions_updateinteraction_1784019432"]
201
+ // CIL[BEGIN chunk_id="ai-interactions_createcilproposal_1784019432" type="function" identity="createCilLearningProposal" parent="none"]
202
+ // CIL[DOC-MACRO purpose="Queue a CIL learning proposal for developer review"]
203
+ // CIL[DOC-RESPONSIBILITY responsibility="Create a cil_learning_proposal item from support case evidence"]
204
+ // CIL[DOC-CONTEXT module="ai-interactions" layer="api-handler" related_files="["custom/apps/cortex/seed/types.json", ".framework/functions/admin-data.ts", ".framework/functions/_shared/schema-utils.ts", "\\\"]"]
205
+ // CIL[DOC-CONTRACT inputs="ticket_id, thread_id, ai_message_id, proposed_summary, source_*" outputs="created_proposal" errors="missing_summary_or_ticket, type_not_found" side_effects="database_record_creation"]
206
+ // CIL[DOC-MICRO logic_summary="Resolves cil_learning_proposal type and creates a draft proposal from support case context" notable_decisions=["Cortex may only create and update proposals; applying them is reserved for the developer workbench."]
207
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="external_symbols_unknown"]
208
+ // CIL[DOC-STABILITY stability="experimental"]
209
+ // CIL[DOC-VECTOR type="context" content="Layer: api-handler. Direct callers: 0. Direct calls: 0. Related files: custom/apps/cortex/seed/types.json, .framework/functions/admin-data.ts, .framework/functions/_shared/schema-utils.ts, \."]
210
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
211
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
212
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
213
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
214
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
215
+ export const createCilLearningProposal = createHandler(async (ctx, body) => {
216
+ const {
217
+ ticket_id, thread_id, ai_message_id, proposed_summary,
218
+ source_message_ids = [], source_chunk_ids = [],
219
+ proposed_tags = []
220
+ } = body || {}
189
221
 
190
- // ─── LIST ─────────────────────────────────────────────────────────────────────
191
- /**
192
- * Lists ai_feedback_record items for the current account.
193
- * Supports filtering by: feedback, kb_candidate, date_from, date_to
194
- */
222
+ if (!ticket_id) throw new Error('ticket_id is required')
223
+ if (!proposed_summary) throw new Error('proposed_summary is required')
224
+
225
+ let typeId: string | null = null
226
+ try {
227
+ typeId = await resolveTypeId('item', 'cil_learning_proposal')
228
+ } catch {
229
+ return { skipped: true, reason: 'cil_learning_proposal type not found' }
230
+ }
231
+ if (!typeId) return { skipped: true, reason: 'cil_learning_proposal type not found' }
232
+
233
+ const record = await create(ctx, {
234
+ entity: 'items',
235
+ type_id: typeId,
236
+ title: `CIL Proposal — ${proposed_summary.slice(0, 80)}`,
237
+ status: 'draft',
238
+ data: {
239
+ ticket_id: ticket_id || null,
240
+ thread_id: thread_id || null,
241
+ ai_message_id: ai_message_id || null,
242
+ proposed_summary: proposed_summary,
243
+ source_message_ids: source_message_ids,
244
+ source_chunk_ids: source_chunk_ids,
245
+ proposed_tags: proposed_tags,
246
+ status: 'draft',
247
+ submitted_at: null,
248
+ reviewed_by: null,
249
+ review_notes: null,
250
+ },
251
+ })
252
+
253
+ return record
254
+ })
255
+ // CIL[END chunk_id="ai-interactions_createcilproposal_1784019432"]
256
+ // CIL[BEGIN chunk_id="ai-interactions_list_1784019432" type="function" identity="list" parent="none"]
257
+ // CIL[DOC-MACRO purpose="List AI interaction records for account"]
258
+ // CIL[DOC-RESPONSIBILITY responsibility="Query and filter interaction records with pagination"]
259
+ // CIL[DOC-CONTEXT module="ai-interactions" layer="api-handler" related_files="[\".framework/src/pages/admin/TypeDetailPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/functions/_shared/schema-utils.ts\",\".framework/functions/_shared/principal.ts\",\"custom/apps/portal/pages/ContentPage.tsx\"]"]
260
+ // CIL[DOC-CONTRACT inputs="none" outputs="interaction_records[]" errors="database_error" side_effects="database_query,rls_filtering"]
261
+ // CIL[DOC-MICRO logic_summary="Builds filtered query for ai_feedback_record type with pagination" notable_decisions="[]"]
262
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
263
+ // CIL[DOC-STABILITY stability="stable"]
264
+ // CIL[DOC-VECTOR type="context" content="Layer: api-handler. Direct callers: 0. Direct calls: 0. Related files: .framework/src/pages/admin/TypeDetailPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/functions/_shared/schema-utils.ts, .framework/functions/_shared/principal.ts, custom/apps/portal/pages/ContentPage.tsx."]
265
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
266
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
267
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
268
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
269
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
195
270
  export const list = createHandler(async (ctx, _body) => {
196
271
  const { feedback, kb_candidate, limit = '50', offset = '0' } = ctx.query || {}
197
272
 
@@ -205,7 +280,6 @@ export const list = createHandler(async (ctx, _body) => {
205
280
  if (feedback) q = q.eq('data->>customer_feedback', feedback)
206
281
  if (kb_candidate !== undefined) q = q.eq('data->>kb_candidate', kb_candidate)
207
282
 
208
- // Filter to ai_feedback_record type only
209
283
  const { data: typeRow } = await adminDb
210
284
  .from('types').select('id').eq('slug', 'ai_feedback_record').eq('kind', 'item').maybeSingle()
211
285
  if (typeRow?.id) q = q.eq('type_id', typeRow.id)
@@ -214,9 +288,21 @@ export const list = createHandler(async (ctx, _body) => {
214
288
  if (error) throw error
215
289
  return data || []
216
290
  })
217
-
218
- // ─── HANDLER ─────────────────────────────────────────────────────────────────
219
-
291
+ // CIL[END chunk_id="ai-interactions_list_1784019432"]
292
+ // CIL[BEGIN chunk_id="ai-interactions_handler_1784019432" type="function" identity="handler" parent="none"]
293
+ // CIL[DOC-MACRO purpose="Route AI interaction requests"]
294
+ // CIL[DOC-RESPONSIBILITY responsibility="Dispatch requests to appropriate interaction handlers"]
295
+ // CIL[DOC-CONTEXT module="ai-interactions" layer="api-handler" related_files="[]"]
296
+ // CIL[DOC-CONTRACT inputs="none" outputs="handler_response" errors="invalid_action_or_method" side_effects="delegates_to_interaction_handlers"]
297
+ // CIL[DOC-MICRO logic_summary="Routes actions to submit_feedback, create_interaction, update_interaction, list" notable_decisions="[]"]
298
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
299
+ // CIL[DOC-STABILITY stability="stable"]
300
+ // CIL[DOC-VECTOR type="context" content="Layer: api-handler. Direct callers: 0. Direct calls: 0. Related files: none."]
301
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
302
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
303
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
304
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
305
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
220
306
  export const handler = createHandler(async (ctx, body) => {
221
307
  const { action } = ctx.query || {}
222
308
  const method = ctx.query?.method || 'GET'
@@ -231,6 +317,9 @@ export const handler = createHandler(async (ctx, body) => {
231
317
  case 'update_interaction':
232
318
  if (method === 'PATCH' || method === 'POST') return await updateInteraction(ctx, body)
233
319
  break
320
+ case 'create_cil_proposal':
321
+ if (method === 'POST') return await createCilLearningProposal(ctx, body)
322
+ break
234
323
  case 'list':
235
324
  default:
236
325
  if (method === 'GET') return await list(ctx, body)
@@ -238,3 +327,4 @@ export const handler = createHandler(async (ctx, body) => {
238
327
 
239
328
  throw new Error('Invalid action or method')
240
329
  })
330
+ // CIL[END chunk_id="ai-interactions_handler_1784019432"]