@m6d/cortex-server 1.8.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (354) hide show
  1. package/README.md +8 -3
  2. package/contracts/README.md +23 -0
  3. package/contracts/graph/embed.ts +50 -0
  4. package/{src/lib → contracts}/graph/helpers.ts +4 -10
  5. package/{src/lib → contracts}/graph/neo4j.ts +14 -27
  6. package/contracts/graph/schema.ts +65 -0
  7. package/{src/lib → contracts}/graph/types.ts +2 -29
  8. package/contracts/graph.ts +36 -0
  9. package/contracts/rich-text.ts +207 -0
  10. package/contracts/runtime.ts +243 -0
  11. package/contracts/wire.ts +143 -0
  12. package/dist/contracts/graph/embed.d.ts +22 -0
  13. package/dist/{src/lib → contracts}/graph/helpers.d.ts +16 -14
  14. package/dist/{src/lib → contracts}/graph/neo4j.d.ts +5 -5
  15. package/dist/contracts/graph/schema.d.ts +62 -0
  16. package/dist/{src/lib → contracts}/graph/types.d.ts +1 -1
  17. package/dist/contracts/graph.d.ts +14 -0
  18. package/dist/contracts/rich-text.d.ts +32 -0
  19. package/dist/contracts/runtime.d.ts +310 -0
  20. package/dist/contracts/wire.d.ts +120 -0
  21. package/dist/src/lib/adapters/database/index.d.ts +61 -0
  22. package/dist/src/lib/adapters/database/message-content.d.ts +30 -0
  23. package/dist/src/lib/adapters/database/mssql/attachments.d.ts +100 -0
  24. package/dist/src/lib/adapters/database/mssql/client.d.ts +8 -0
  25. package/dist/src/lib/adapters/database/mssql/index.d.ts +194 -0
  26. package/dist/src/lib/adapters/database/mssql/llm-requests.d.ts +17 -0
  27. package/dist/src/lib/adapters/database/mssql/messages.d.ts +37 -0
  28. package/dist/src/lib/adapters/database/mssql/threads.d.ts +50 -0
  29. package/dist/src/lib/adapters/database/postgres/attachments.d.ts +113 -0
  30. package/dist/src/lib/adapters/database/postgres/client.d.ts +8 -0
  31. package/dist/src/lib/adapters/database/postgres/index.d.ts +207 -0
  32. package/dist/src/lib/adapters/database/postgres/llm-requests.d.ts +17 -0
  33. package/dist/src/lib/adapters/database/postgres/messages.d.ts +37 -0
  34. package/dist/src/lib/adapters/database/postgres/threads.d.ts +50 -0
  35. package/{src/lib/adapters/storage.ts → dist/src/lib/adapters/storage/index.d.ts} +1 -1
  36. package/dist/src/lib/adapters/{minio.d.ts → storage/minio.d.ts} +1 -1
  37. package/dist/src/lib/ai/active-runs.d.ts +63 -0
  38. package/dist/src/lib/ai/attachments.d.ts +30 -0
  39. package/dist/src/lib/ai/backend-url.d.ts +16 -0
  40. package/dist/src/lib/ai/cc-runtime.d.ts +61 -0
  41. package/dist/src/lib/ai/commit-gate.d.ts +21 -0
  42. package/dist/src/lib/ai/context/builder.d.ts +6 -7
  43. package/dist/src/lib/ai/context/compression-middleware.d.ts +15 -0
  44. package/dist/src/lib/ai/context/compressor.d.ts +2 -13
  45. package/dist/src/lib/ai/context/intra-turn-compressor.d.ts +9 -9
  46. package/dist/src/lib/ai/context/optimize-thread-context.d.ts +9 -0
  47. package/dist/src/lib/ai/context/summarizer.d.ts +3 -3
  48. package/dist/src/lib/ai/context/token-estimator.d.ts +5 -8
  49. package/dist/src/lib/ai/fetch.d.ts +1 -1
  50. package/dist/src/lib/ai/finish-turn.d.ts +23 -0
  51. package/dist/src/lib/ai/helpers.d.ts +37 -4
  52. package/dist/src/lib/ai/index.d.ts +6 -3
  53. package/dist/src/lib/ai/inspector.d.ts +41 -0
  54. package/dist/src/lib/ai/interceptors/request-interceptor.d.ts +6 -5
  55. package/dist/src/lib/ai/prompt.d.ts +5 -4
  56. package/dist/src/lib/ai/redis-runs.d.ts +41 -0
  57. package/dist/src/lib/ai/redis-stream-log.d.ts +39 -0
  58. package/dist/src/lib/ai/tools/execute-code.tool.d.ts +18 -4
  59. package/dist/src/lib/ai/tools/query-graph.tool.d.ts +13 -5
  60. package/dist/src/lib/ai/tools/read-attachment.tool.d.ts +21 -0
  61. package/dist/src/lib/ai/tools/search-common.d.ts +17 -0
  62. package/dist/src/lib/ai/tools/search-knowledge.tool.d.ts +15 -0
  63. package/dist/src/lib/ai/tools/search-services.tool.d.ts +12 -0
  64. package/dist/src/lib/ai/tools/search-tools.tool.d.ts +12 -0
  65. package/dist/src/lib/ai/turn-tools.d.ts +39 -0
  66. package/dist/src/lib/ai/vision/rasterize-pdf.d.ts +26 -0
  67. package/dist/src/lib/ai/vision/rasterize-pdf.worker.d.ts +1 -0
  68. package/dist/src/lib/ai/vision/vision-reader.d.ts +45 -0
  69. package/dist/src/lib/cc/client.d.ts +183 -0
  70. package/dist/src/lib/cc/config-cache.d.ts +20 -0
  71. package/dist/src/lib/cc/format.d.ts +23 -0
  72. package/dist/src/lib/cc/registry.d.ts +34 -0
  73. package/dist/src/lib/cc/types.d.ts +27 -0
  74. package/dist/src/lib/config.d.ts +81 -64
  75. package/dist/src/lib/db/drizzle.config.mssql.d.ts +2 -0
  76. package/dist/src/lib/db/drizzle.config.pg.d.ts +2 -0
  77. package/dist/src/lib/db/migrate.d.ts +7 -1
  78. package/dist/src/lib/db/{schema.d.ts → schema.mssql.d.ts} +138 -29
  79. package/dist/src/lib/db/schema.pg.d.ts +546 -0
  80. package/dist/src/lib/factory.d.ts +2 -12
  81. package/dist/src/lib/graph/index.d.ts +10 -11
  82. package/dist/src/lib/graph/resolver.d.ts +2 -3
  83. package/dist/src/lib/index.d.ts +3 -3
  84. package/dist/src/lib/redis.d.ts +19 -0
  85. package/dist/src/lib/routes/chat.d.ts +1 -1
  86. package/dist/src/lib/routes/files.d.ts +1 -1
  87. package/dist/src/lib/routes/owned-thread.d.ts +17 -0
  88. package/dist/src/lib/routes/threads.d.ts +1 -1
  89. package/dist/src/lib/routes/ws.d.ts +1 -1
  90. package/dist/src/lib/types.d.ts +20 -37
  91. package/dist/src/lib/ws/connections.d.ts +2 -1
  92. package/package.json +33 -18
  93. package/src/lib/adapters/database/index.ts +78 -0
  94. package/src/lib/adapters/database/message-content.ts +39 -0
  95. package/src/lib/adapters/database/mssql/attachments.ts +90 -0
  96. package/src/lib/adapters/database/mssql/client.ts +11 -0
  97. package/src/lib/adapters/database/mssql/index.ts +23 -0
  98. package/src/lib/adapters/database/mssql/llm-requests.ts +43 -0
  99. package/src/lib/adapters/database/mssql/messages.ts +92 -0
  100. package/src/lib/adapters/database/mssql/threads.ts +83 -0
  101. package/src/lib/adapters/database/postgres/attachments.ts +88 -0
  102. package/src/lib/adapters/database/postgres/client.ts +11 -0
  103. package/src/lib/adapters/database/postgres/index.ts +23 -0
  104. package/src/lib/adapters/database/postgres/llm-requests.ts +45 -0
  105. package/src/lib/adapters/database/postgres/messages.ts +92 -0
  106. package/src/lib/adapters/database/postgres/threads.ts +84 -0
  107. package/{dist/src/lib/adapters/storage.d.ts → src/lib/adapters/storage/index.ts} +1 -1
  108. package/src/lib/adapters/{minio.ts → storage/minio.ts} +5 -5
  109. package/src/lib/ai/active-runs.ts +157 -0
  110. package/src/lib/ai/attachments.ts +144 -0
  111. package/src/lib/ai/backend-url.ts +27 -0
  112. package/src/lib/ai/cc-runtime.ts +63 -0
  113. package/src/lib/ai/commit-gate.ts +116 -0
  114. package/src/lib/ai/context/builder.ts +12 -14
  115. package/src/lib/ai/context/compression-middleware.ts +44 -0
  116. package/src/lib/ai/context/compressor.ts +67 -59
  117. package/src/lib/ai/context/intra-turn-compressor.ts +121 -204
  118. package/src/lib/ai/context/optimize-thread-context.ts +50 -0
  119. package/src/lib/ai/context/summarizer.ts +28 -30
  120. package/src/lib/ai/context/token-estimator.ts +35 -30
  121. package/src/lib/ai/fetch.ts +10 -5
  122. package/src/lib/ai/finish-turn.ts +75 -0
  123. package/src/lib/ai/helpers.ts +83 -15
  124. package/src/lib/ai/index.ts +366 -329
  125. package/src/lib/ai/inspector.ts +112 -0
  126. package/src/lib/ai/interceptors/request-interceptor.ts +70 -42
  127. package/src/lib/ai/prompt.ts +126 -125
  128. package/src/lib/ai/redis-runs.ts +167 -0
  129. package/src/lib/ai/redis-stream-log.ts +219 -0
  130. package/src/lib/ai/tools/execute-code.tool.ts +178 -67
  131. package/src/lib/ai/tools/query-graph.tool.ts +7 -8
  132. package/src/lib/ai/tools/read-attachment.tool.ts +59 -0
  133. package/src/lib/ai/tools/search-common.ts +15 -0
  134. package/src/lib/ai/tools/search-knowledge.tool.ts +33 -0
  135. package/src/lib/ai/tools/search-services.tool.ts +31 -0
  136. package/src/lib/ai/tools/search-tools.tool.ts +29 -0
  137. package/src/lib/ai/turn-tools.ts +154 -0
  138. package/src/lib/ai/vision/rasterize-pdf.ts +69 -0
  139. package/src/lib/ai/vision/rasterize-pdf.worker.ts +81 -0
  140. package/src/lib/ai/vision/vision-reader.ts +130 -0
  141. package/src/lib/auth/middleware.ts +5 -3
  142. package/src/lib/cc/client.ts +273 -0
  143. package/src/lib/cc/config-cache.ts +32 -0
  144. package/src/lib/cc/format.ts +92 -0
  145. package/src/lib/cc/registry.ts +62 -0
  146. package/src/lib/cc/types.ts +44 -0
  147. package/src/lib/config.ts +102 -71
  148. package/src/lib/db/drizzle.config.mssql.ts +9 -0
  149. package/src/lib/db/drizzle.config.pg.ts +9 -0
  150. package/src/lib/db/migrate.ts +45 -10
  151. package/src/lib/db/migrations/mssql/20260729092726_talented_wilson_fisk/migration.sql +20 -0
  152. package/src/lib/db/migrations/mssql/20260729092726_talented_wilson_fisk/snapshot.json +497 -0
  153. package/src/lib/db/migrations/mssql/20260801003652_perpetual_blue_shield/migration.sql +1 -0
  154. package/src/lib/db/migrations/mssql/20260801003652_perpetual_blue_shield/snapshot.json +516 -0
  155. package/src/lib/db/migrations/mssql/20260812174642_user_id_text/migration.sql +2 -0
  156. package/src/lib/db/migrations/mssql/20260812174642_user_id_text/snapshot.json +516 -0
  157. package/src/lib/db/migrations/pg/20260801084117_thick_ben_grimm/migration.sql +53 -0
  158. package/src/lib/db/migrations/pg/20260801084117_thick_ben_grimm/snapshot.json +584 -0
  159. package/src/lib/db/migrations/pg/20260812174622_user_id_text/migration.sql +2 -0
  160. package/src/lib/db/migrations/pg/20260812174622_user_id_text/snapshot.json +584 -0
  161. package/src/lib/db/{schema.ts → schema.mssql.ts} +29 -18
  162. package/src/lib/db/schema.pg.ts +95 -0
  163. package/src/lib/factory.ts +44 -89
  164. package/src/lib/graph/index.ts +12 -40
  165. package/src/lib/graph/resolver.ts +146 -116
  166. package/src/lib/index.ts +11 -4
  167. package/src/lib/redis.ts +44 -0
  168. package/src/lib/routes/chat.ts +91 -62
  169. package/src/lib/routes/files.ts +105 -83
  170. package/src/lib/routes/owned-thread.ts +17 -0
  171. package/src/lib/routes/threads.ts +14 -30
  172. package/src/lib/routes/ws.ts +9 -3
  173. package/src/lib/types.ts +37 -36
  174. package/src/lib/ws/connections.ts +9 -1
  175. package/tsconfig.json +48 -0
  176. package/dist/src/lib/adapters/database.d.ts +0 -45
  177. package/dist/src/lib/adapters/mssql.d.ts +0 -3
  178. package/dist/src/lib/ai/active-streams.d.ts +0 -14
  179. package/dist/src/lib/ai/context/index.d.ts +0 -16
  180. package/dist/src/lib/ai/tools/capture-files.tool.d.ts +0 -6
  181. package/dist/src/lib/cli/extract-endpoints.d.ts +0 -6
  182. package/dist/src/lib/graph/expand-domains.d.ts +0 -2
  183. package/dist/src/lib/graph/generate-cypher.d.ts +0 -22
  184. package/dist/src/lib/graph/seed.d.ts +0 -19
  185. package/dist/src/lib/graph/validate.d.ts +0 -2
  186. package/dist/src/lib/routes/index.d.ts +0 -4
  187. package/dist/src/lib/ws/events.d.ts +0 -39
  188. package/dist/src/lib/ws/index.d.ts +0 -3
  189. package/dist/src/lib/ws/notify.d.ts +0 -2
  190. package/src/lib/adapters/database.ts +0 -48
  191. package/src/lib/adapters/mssql.ts +0 -231
  192. package/src/lib/ai/active-streams.ts +0 -123
  193. package/src/lib/ai/context/index.ts +0 -80
  194. package/src/lib/ai/tools/capture-files.tool.ts +0 -20
  195. package/src/lib/cli/extract-endpoints.ts +0 -550
  196. package/src/lib/graph/expand-domains.ts +0 -276
  197. package/src/lib/graph/generate-cypher.ts +0 -192
  198. package/src/lib/graph/seed.ts +0 -162
  199. package/src/lib/graph/validate.ts +0 -78
  200. package/src/lib/routes/index.ts +0 -4
  201. package/src/lib/ws/events.ts +0 -39
  202. package/src/lib/ws/index.ts +0 -11
  203. package/src/lib/ws/notify.ts +0 -9
  204. package/src/sample/db/client.ts +0 -9
  205. package/src/sample/db/migrations/20260411023125_rich_purple_man/migration.sql +0 -5
  206. package/src/sample/db/migrations/20260411023125_rich_purple_man/snapshot.json +0 -50
  207. package/src/sample/db/schema.ts +0 -10
  208. package/src/sample/domains/account/concepts/session.concept.ts +0 -17
  209. package/src/sample/domains/account/endpoints/listCurrentSessions.endpoint.ts +0 -31
  210. package/src/sample/domains/account/endpoints/revokeAllOtherSessions.endpoint.ts +0 -22
  211. package/src/sample/domains/account/endpoints/revokeCurrentSession.endpoint.ts +0 -33
  212. package/src/sample/domains/account/index.ts +0 -18
  213. package/src/sample/domains/appraisals/concepts/appraisalCycle.concept.ts +0 -15
  214. package/src/sample/domains/appraisals/concepts/appraisalRecord.concept.ts +0 -20
  215. package/src/sample/domains/appraisals/concepts/appraisalRecordCompetency.concept.ts +0 -10
  216. package/src/sample/domains/appraisals/concepts/appraisalRecordFunctionalRequirement.concept.ts +0 -10
  217. package/src/sample/domains/appraisals/concepts/appraisalRecordGoal.concept.ts +0 -17
  218. package/src/sample/domains/appraisals/endpoints/getAppraisalRecordById.endpoint.ts +0 -321
  219. package/src/sample/domains/appraisals/endpoints/getAppraisalRecordCompetencies.endpoint.ts +0 -120
  220. package/src/sample/domains/appraisals/endpoints/getAppraisalRecordFunctionalRequirements.endpoint.ts +0 -126
  221. package/src/sample/domains/appraisals/endpoints/getAppraisalRecordGoals.endpoint.ts +0 -104
  222. package/src/sample/domains/appraisals/endpoints/getAppraisalRecordScore.endpoint.ts +0 -58
  223. package/src/sample/domains/appraisals/endpoints/listAppraisalCyclesSimple.endpoint.ts +0 -52
  224. package/src/sample/domains/appraisals/endpoints/listAppraisalRecords.endpoint.ts +0 -245
  225. package/src/sample/domains/appraisals/endpoints/listAppraisalTemplatesSimple.endpoint.ts +0 -52
  226. package/src/sample/domains/appraisals/index.ts +0 -40
  227. package/src/sample/domains/appraisals/rules/appraisalRecordScoping.rule.ts +0 -7
  228. package/src/sample/domains/attendance/concepts/attendancePermission.concept.ts +0 -17
  229. package/src/sample/domains/attendance/concepts/attendanceTransaction.concept.ts +0 -17
  230. package/src/sample/domains/attendance/concepts/publicHoliday.concept.ts +0 -10
  231. package/src/sample/domains/attendance/concepts/punch.concept.ts +0 -19
  232. package/src/sample/domains/attendance/endpoints/getAttendanceTransactionById.endpoint.ts +0 -444
  233. package/src/sample/domains/attendance/endpoints/getCurrentAttendanceProfile.endpoint.ts +0 -886
  234. package/src/sample/domains/attendance/endpoints/getCurrentAttendanceStatistics.endpoint.ts +0 -49
  235. package/src/sample/domains/attendance/endpoints/listAttendancePermissions.endpoint.ts +0 -176
  236. package/src/sample/domains/attendance/endpoints/listAttendanceTransactionStates.endpoint.ts +0 -26
  237. package/src/sample/domains/attendance/endpoints/listAttendanceTransactions.endpoint.ts +0 -373
  238. package/src/sample/domains/attendance/endpoints/listPublicHolidaysSimple.endpoint.ts +0 -52
  239. package/src/sample/domains/attendance/endpoints/listPunchTypes.endpoint.ts +0 -25
  240. package/src/sample/domains/attendance/endpoints/listPunches.endpoint.ts +0 -178
  241. package/src/sample/domains/attendance/index.ts +0 -41
  242. package/src/sample/domains/attendance/services/attendancePermissions.service.ts +0 -15
  243. package/src/sample/domains/employees/concepts/employee.concept.ts +0 -20
  244. package/src/sample/domains/employees/concepts/employeeBankAccount.concept.ts +0 -19
  245. package/src/sample/domains/employees/concepts/employeeChild.concept.ts +0 -19
  246. package/src/sample/domains/employees/concepts/employeeDocument.concept.ts +0 -21
  247. package/src/sample/domains/employees/concepts/employeeEvent.concept.ts +0 -21
  248. package/src/sample/domains/employees/concepts/employeeExperience.concept.ts +0 -18
  249. package/src/sample/domains/employees/concepts/employeeJobLevelChange.concept.ts +0 -21
  250. package/src/sample/domains/employees/concepts/employeeMedal.concept.ts +0 -20
  251. package/src/sample/domains/employees/concepts/employeeQualification.concept.ts +0 -20
  252. package/src/sample/domains/employees/concepts/employeeSpouse.concept.ts +0 -21
  253. package/src/sample/domains/employees/concepts/employeeViolation.concept.ts +0 -19
  254. package/src/sample/domains/employees/endpoints/getCurrentEmployee.endpoint.ts +0 -1651
  255. package/src/sample/domains/employees/endpoints/getCurrentIdentity.endpoint.ts +0 -197
  256. package/src/sample/domains/employees/endpoints/getCurrentManagers.endpoint.ts +0 -142
  257. package/src/sample/domains/employees/endpoints/getEmployeeById.endpoint.ts +0 -1659
  258. package/src/sample/domains/employees/endpoints/getEmployeeStatistics.endpoint.ts +0 -43
  259. package/src/sample/domains/employees/endpoints/listBankAccounts.endpoint.ts +0 -223
  260. package/src/sample/domains/employees/endpoints/listChildren.endpoint.ts +0 -211
  261. package/src/sample/domains/employees/endpoints/listDocuments.endpoint.ts +0 -222
  262. package/src/sample/domains/employees/endpoints/listEmployeesSimple.endpoint.ts +0 -156
  263. package/src/sample/domains/employees/endpoints/listEvents.endpoint.ts +0 -120
  264. package/src/sample/domains/employees/endpoints/listExperiences.endpoint.ts +0 -188
  265. package/src/sample/domains/employees/endpoints/listJobLevelChanges.endpoint.ts +0 -240
  266. package/src/sample/domains/employees/endpoints/listMedals.endpoint.ts +0 -266
  267. package/src/sample/domains/employees/endpoints/listQualifications.endpoint.ts +0 -265
  268. package/src/sample/domains/employees/endpoints/listSpouses.endpoint.ts +0 -278
  269. package/src/sample/domains/employees/endpoints/listViolations.endpoint.ts +0 -245
  270. package/src/sample/domains/employees/index.ts +0 -75
  271. package/src/sample/domains/employees/services/employees.service.ts +0 -181
  272. package/src/sample/domains/index.ts +0 -10
  273. package/src/sample/domains/leaves/concepts/leave.concept.ts +0 -21
  274. package/src/sample/domains/leaves/concepts/leaveBalance.concept.ts +0 -17
  275. package/src/sample/domains/leaves/concepts/leaveBalanceTransaction.concept.ts +0 -16
  276. package/src/sample/domains/leaves/concepts/leaveType.concept.ts +0 -13
  277. package/src/sample/domains/leaves/concepts/leaveTypes.concept.ts +0 -205
  278. package/src/sample/domains/leaves/endpoints/getBalance.endpoint.ts +0 -53
  279. package/src/sample/domains/leaves/endpoints/getLeaveById.endpoint.ts +0 -53
  280. package/src/sample/domains/leaves/endpoints/listBalanceTransactions.endpoint.ts +0 -196
  281. package/src/sample/domains/leaves/endpoints/listBalanceTypes.endpoint.ts +0 -26
  282. package/src/sample/domains/leaves/endpoints/listBalances.endpoint.ts +0 -201
  283. package/src/sample/domains/leaves/endpoints/listLeaveTypes.endpoint.ts +0 -28
  284. package/src/sample/domains/leaves/endpoints/listLeaves.endpoint.ts +0 -234
  285. package/src/sample/domains/leaves/index.ts +0 -38
  286. package/src/sample/domains/leaves/services/leaveRequests.service.ts +0 -232
  287. package/src/sample/domains/notifications/concepts/notification.concept.ts +0 -19
  288. package/src/sample/domains/notifications/endpoints/countMyNotifications.endpoint.ts +0 -21
  289. package/src/sample/domains/notifications/endpoints/getMyNotification.endpoint.ts +0 -57
  290. package/src/sample/domains/notifications/endpoints/listMyNotifications.endpoint.ts +0 -59
  291. package/src/sample/domains/notifications/endpoints/markMyNotificationAsRead.endpoint.ts +0 -32
  292. package/src/sample/domains/notifications/index.ts +0 -20
  293. package/src/sample/domains/payroll/concepts/payslip.concept.ts +0 -18
  294. package/src/sample/domains/payroll/concepts/salaryCertificate.concept.ts +0 -17
  295. package/src/sample/domains/payroll/concepts/salaryCertificateRequestingEntity.concept.ts +0 -8
  296. package/src/sample/domains/payroll/endpoints/getPayslipById.endpoint.ts +0 -238
  297. package/src/sample/domains/payroll/endpoints/listPayslips.endpoint.ts +0 -216
  298. package/src/sample/domains/payroll/endpoints/listSalaryCertificateLanguages.endpoint.ts +0 -25
  299. package/src/sample/domains/payroll/endpoints/listSalaryCertificateRequestingEntities.endpoint.ts +0 -62
  300. package/src/sample/domains/payroll/endpoints/listSalaryCertificateTypes.endpoint.ts +0 -24
  301. package/src/sample/domains/payroll/endpoints/listSalaryCertificates.endpoint.ts +0 -122
  302. package/src/sample/domains/payroll/endpoints/previewSalaryCertificate.endpoint.ts +0 -45
  303. package/src/sample/domains/payroll/index.ts +0 -32
  304. package/src/sample/domains/payroll/rules/payrollEmployeeContext.rule.ts +0 -7
  305. package/src/sample/domains/payroll/services/salaryCertificates.service.ts +0 -15
  306. package/src/sample/domains/servicing/concepts/service.concept.ts +0 -6
  307. package/src/sample/domains/servicing/concepts/serviceRequest.concept.ts +0 -12
  308. package/src/sample/domains/servicing/concepts/serviceRequestApproval.concept.ts +0 -9
  309. package/src/sample/domains/servicing/endpoints/cancelServiceRequest.endpoint.ts +0 -21
  310. package/src/sample/domains/servicing/endpoints/createServiceRequest.endpoint.ts +0 -511
  311. package/src/sample/domains/servicing/endpoints/getServiceRequest.endpoint.ts +0 -352
  312. package/src/sample/domains/servicing/endpoints/getServiceRequestFormItems.endpoint.ts +0 -219
  313. package/src/sample/domains/servicing/endpoints/getServiceRequestTransactionFormItems.endpoint.ts +0 -216
  314. package/src/sample/domains/servicing/endpoints/getServiceStates.endpoint.ts +0 -47
  315. package/src/sample/domains/servicing/endpoints/invokeServiceRequestAction.endpoint.ts +0 -139
  316. package/src/sample/domains/servicing/endpoints/listServiceRequests.endpoint.ts +0 -292
  317. package/src/sample/domains/servicing/endpoints/listServices.endpoint.ts +0 -108
  318. package/src/sample/domains/servicing/endpoints/updateServiceRequest.endpoint.ts +0 -355
  319. package/src/sample/domains/servicing/index.ts +0 -44
  320. package/src/sample/domains/servicing/rules/checkValidActions.rule.ts +0 -7
  321. package/src/sample/domains/servicing/rules/createServiceRequest.rule.ts +0 -7
  322. package/src/sample/domains/servicing/rules/filterServiceRequestsByState.rule.ts +0 -7
  323. package/src/sample/domains/servicing/rules/passingOptionFields.rule.ts +0 -7
  324. package/src/sample/domains/shared/rules/pagination.rule.ts +0 -7
  325. package/src/sample/domains/suggestions/concepts/suggestion.concept.ts +0 -19
  326. package/src/sample/domains/suggestions/concepts/suggestionCategory.concept.ts +0 -7
  327. package/src/sample/domains/suggestions/concepts/suggestionImpactLevel.concept.ts +0 -7
  328. package/src/sample/domains/suggestions/endpoints/createSuggestion.endpoint.ts +0 -705
  329. package/src/sample/domains/suggestions/endpoints/deleteSuggestion.endpoint.ts +0 -32
  330. package/src/sample/domains/suggestions/endpoints/getSuggestionById.endpoint.ts +0 -635
  331. package/src/sample/domains/suggestions/endpoints/listSuggestionCategories.endpoint.ts +0 -62
  332. package/src/sample/domains/suggestions/endpoints/listSuggestionImpactLevels.endpoint.ts +0 -62
  333. package/src/sample/domains/suggestions/endpoints/listSuggestionStates.endpoint.ts +0 -24
  334. package/src/sample/domains/suggestions/endpoints/listSuggestions.endpoint.ts +0 -132
  335. package/src/sample/domains/suggestions/endpoints/updateSuggestion.endpoint.ts +0 -690
  336. package/src/sample/domains/suggestions/endpoints/updateSuggestionState.endpoint.ts +0 -39
  337. package/src/sample/domains/suggestions/index.ts +0 -34
  338. package/src/sample/domains/suggestions/rules/suggestionScope.rule.ts +0 -7
  339. package/src/sample/domains/surveys/concepts/survey.concept.ts +0 -10
  340. package/src/sample/domains/surveys/concepts/surveyResponse.concept.ts +0 -14
  341. package/src/sample/domains/surveys/endpoints/getSurveyResponseById.endpoint.ts +0 -131
  342. package/src/sample/domains/surveys/endpoints/getTargetedSurvey.endpoint.ts +0 -129
  343. package/src/sample/domains/surveys/endpoints/listTargetedSurveys.endpoint.ts +0 -160
  344. package/src/sample/domains/surveys/endpoints/respondToSurvey.endpoint.ts +0 -144
  345. package/src/sample/domains/surveys/index.ts +0 -21
  346. package/src/sample/drizzle.config.ts +0 -11
  347. package/src/sample/index.bak.ts +0 -341
  348. package/src/sample/index.ts +0 -318
  349. package/src/sample/official-statements/defaults.ts +0 -57
  350. package/src/sample/official-statements/routes.ts +0 -137
  351. package/src/sample/official-statements/service.ts +0 -148
  352. package/src/sample/official-statements/types.ts +0 -23
  353. /package/src/lib/db/migrations/{20260326231647_nice_speedball → mssql/20260326231647_nice_speedball}/migration.sql +0 -0
  354. /package/src/lib/db/migrations/{20260326231647_nice_speedball → mssql/20260326231647_nice_speedball}/snapshot.json +0 -0
@@ -0,0 +1,112 @@
1
+ import type { ChatMiddleware, TokenUsage as ProviderTokenUsage } from "@tanstack/ai";
2
+ import type { TokenUsage } from "@/types";
3
+
4
+ /** One model call's raw exchange, as the LLM request inspector renders it. */
5
+ export type CapturedStep = {
6
+ prompt: string;
7
+ output: string | null;
8
+ tokenUsage: TokenUsage | null;
9
+ };
10
+
11
+ /**
12
+ * Watches one turn's model calls. The SDK's `debug` logger reports call metadata
13
+ * but never raw bodies, so the raw exchange is captured where it actually
14
+ * exists — on the HTTP client — while usage arrives through middleware.
15
+ */
16
+ export function createInspector() {
17
+ const steps: CapturedStep[] = [];
18
+ let modelId = "";
19
+ let tokenUsage: TokenUsage | undefined;
20
+
21
+ async function capturingFetch(input: string | URL | Request, init?: RequestInit) {
22
+ const step: CapturedStep = {
23
+ prompt: typeof init?.body === "string" ? init.body : "",
24
+ output: null,
25
+ tokenUsage: null,
26
+ };
27
+ steps.push(step);
28
+
29
+ const response = await fetch(input, init);
30
+ // Drain a tee rather than the response itself: the model call must keep
31
+ // streaming at full speed, and losing debug data must never fail a turn.
32
+ void response
33
+ .clone()
34
+ .text()
35
+ .then(function (text) {
36
+ step.output = text;
37
+ })
38
+ .catch(() => undefined);
39
+
40
+ return response;
41
+ }
42
+
43
+ const middleware: ChatMiddleware = {
44
+ name: "cortex-inspector",
45
+ onUsage(ctx, usage) {
46
+ modelId = ctx.model;
47
+ const stepUsage = toTokenUsage(usage);
48
+ const lastStep = steps.at(-1);
49
+ if (lastStep) lastStep.tokenUsage = stepUsage;
50
+ tokenUsage = addTokenUsage(tokenUsage, stepUsage);
51
+ },
52
+ };
53
+
54
+ return {
55
+ steps,
56
+ middleware,
57
+ // Bun's fetch type carries preconnect; delegate so the client accepts the shim.
58
+ fetch: Object.assign(capturingFetch, { preconnect: fetch.preconnect }),
59
+ get modelId() {
60
+ return modelId;
61
+ },
62
+ get tokenUsage() {
63
+ return tokenUsage;
64
+ },
65
+ };
66
+ }
67
+
68
+ /**
69
+ * Flattens the provider's usage shape into ours. The provider reports cached and
70
+ * cache-written prompt tokens but no uncached counter, so that dimension is the
71
+ * remainder — which is what makes the client's breakdown add up to the total.
72
+ */
73
+ export function toTokenUsage(usage: ProviderTokenUsage) {
74
+ const cacheRead = usage.promptTokensDetails?.cachedTokens ?? 0;
75
+ const cacheWrite = usage.promptTokensDetails?.cacheWriteTokens ?? 0;
76
+ const reasoning = usage.completionTokensDetails?.reasoningTokens ?? 0;
77
+
78
+ return {
79
+ input: {
80
+ noCache: Math.max(usage.promptTokens - cacheRead - cacheWrite, 0),
81
+ cacheRead,
82
+ cacheWrite,
83
+ total: usage.promptTokens,
84
+ },
85
+ output: {
86
+ reasoning,
87
+ text: usage.completionTokensDetails?.textTokens ?? usage.completionTokens - reasoning,
88
+ total: usage.completionTokens,
89
+ },
90
+ total: usage.totalTokens,
91
+ } satisfies TokenUsage;
92
+ }
93
+
94
+ /** The agent loop reports usage per iteration; a turn's cost is their sum. */
95
+ function addTokenUsage(left: TokenUsage | undefined, right: TokenUsage) {
96
+ if (!left) return right;
97
+
98
+ return {
99
+ input: {
100
+ noCache: left.input.noCache + right.input.noCache,
101
+ cacheRead: left.input.cacheRead + right.input.cacheRead,
102
+ cacheWrite: left.input.cacheWrite + right.input.cacheWrite,
103
+ total: left.input.total + right.input.total,
104
+ },
105
+ output: {
106
+ reasoning: left.output.reasoning + right.output.reasoning,
107
+ text: left.output.text + right.output.text,
108
+ total: left.output.total + right.output.total,
109
+ },
110
+ total: left.total + right.total,
111
+ } satisfies TokenUsage;
112
+ }
@@ -1,6 +1,6 @@
1
- import type { DatabaseAdapter } from "../../adapters/database.ts";
2
- import type { StorageAdapter } from "../../adapters/storage.ts";
3
- import { streamToBase64, tokenToUserId } from "../helpers.ts";
1
+ import type { DatabaseAdapter } from "@/adapters/database/index";
2
+ import type { StorageAdapter } from "@/adapters/storage/index";
3
+ import { streamToBase64 } from "@/ai/helpers";
4
4
 
5
5
  export type ResolvedFile = {
6
6
  name: string;
@@ -14,48 +14,76 @@ export type RequestInterceptorOptions = {
14
14
  export function createRequestInterceptor(
15
15
  db: DatabaseAdapter,
16
16
  storage: StorageAdapter,
17
- options?: RequestInterceptorOptions,
17
+ options: RequestInterceptorOptions & { threadId: string; userId: string },
18
18
  ) {
19
- const transformFile = options?.transformFile ?? ((file: ResolvedFile) => file);
20
-
21
- return async function resolveRequestBody(
22
- body: Record<string, unknown>,
23
- context: { token: string },
24
- ) {
25
- const userId = tokenToUserId(context.token);
26
-
27
- async function traverse(obj: Record<string, unknown>) {
28
- await Promise.all(
29
- Object.keys(obj).map(async (key) => {
30
- const value = obj[key];
31
- if (typeof value === "string" && value.startsWith("capturedFile")) {
32
- const [_, uploadId] = value.split("#");
33
- const file = await db.capturedFiles.getById(uploadId!, userId);
34
- if (file) {
35
- const fileStream = await storage.stream(`captured_files/${uploadId}`);
36
- const bytes = await streamToBase64(fileStream);
37
- obj[key] = transformFile({ name: file.name, bytes });
38
- }
39
- }
40
-
41
- if (Array.isArray(value)) {
42
- await Promise.all(
43
- value.map(async (child) => {
44
- if (typeof child === "object" && child !== null) {
45
- await traverse(child as Record<string, unknown>);
46
- }
47
- }),
48
- );
49
- }
50
-
51
- if (typeof value === "object" && value !== null && !Array.isArray(value)) {
52
- await traverse(value as Record<string, unknown>);
53
- }
54
- }),
55
- );
19
+ const transformFile = options.transformFile ?? ((file: ResolvedFile) => file);
20
+
21
+ return async function resolveRequestBody(body: Record<string, unknown>) {
22
+ const resolvedAttachments = new Map<string, { value: unknown }>();
23
+ const pending = Object.entries(body).map(([key, value]) => ({
24
+ value,
25
+ replace: (resolved: unknown) => {
26
+ body[key] = resolved;
27
+ },
28
+ }));
29
+
30
+ async function resolveAttachment(id: string) {
31
+ const cached = resolvedAttachments.get(id);
32
+ if (cached) return cached;
33
+
34
+ const attachment = await db.attachments.getById(id, options.userId);
35
+ if (!attachment || attachment.threadId !== options.threadId) {
36
+ throw new Error(`Attachment "${id}" is not available in this thread`);
37
+ }
38
+
39
+ let bytes: string;
40
+ try {
41
+ bytes = await streamToBase64(await storage.stream(attachment.storageKey));
42
+ } catch (error) {
43
+ throw new Error(`Attachment "${id}" could not be loaded from storage`, {
44
+ cause: error,
45
+ });
46
+ }
47
+ const resolved = { value: transformFile({ name: attachment.filename, bytes }) };
48
+ resolvedAttachments.set(id, resolved);
49
+ return resolved;
50
+ }
51
+
52
+ while (pending.length) {
53
+ const { value, replace } = pending.pop()!;
54
+
55
+ if (Array.isArray(value)) {
56
+ const items: unknown[] = value;
57
+ pending.push(
58
+ ...items.map((child, index) => ({
59
+ value: child,
60
+ replace: (resolved: unknown) => {
61
+ items[index] = resolved;
62
+ },
63
+ })),
64
+ );
65
+ continue;
66
+ }
67
+
68
+ if (typeof value === "object" && value !== null) {
69
+ const object = value as Record<string, unknown>;
70
+ pending.push(
71
+ ...Object.entries(object).map(([key, child]) => ({
72
+ value: child,
73
+ replace: (resolved: unknown) => {
74
+ object[key] = resolved;
75
+ },
76
+ })),
77
+ );
78
+ continue;
79
+ }
80
+
81
+ if (typeof value !== "string" || !value.startsWith("attachment#")) continue;
82
+
83
+ const resolved = await resolveAttachment(value.slice("attachment#".length));
84
+ replace(resolved.value);
56
85
  }
57
86
 
58
- await traverse(body);
59
87
  return body;
60
88
  };
61
89
  }
@@ -1,6 +1,8 @@
1
- import type { ResolvedContext, ResolvedEndpoint, ResolvedService } from "../graph/resolver.ts";
2
- import type { PromptContext, ResolvedCortexAgentConfig } from "../config.ts";
3
- import type { Thread } from "../types.ts";
1
+ import type { ResolvedContext, ResolvedEndpoint, ResolvedService } from "@/graph/resolver";
2
+ import type { PromptContext, ResolvedCortexAgentConfig } from "@/config";
3
+ import type { Thread } from "@/types";
4
+ import type { CcPromptInput } from "@/cc/format";
5
+ import { buildCcSection } from "@/cc/format";
4
6
 
5
7
  /**
6
8
  * Resolves session data for the thread, loading from the configured
@@ -27,29 +29,37 @@ export async function buildSystemPrompt(
27
29
  config: ResolvedCortexAgentConfig,
28
30
  resolved: ResolvedContext | null,
29
31
  promptContext: PromptContext,
32
+ cc?: CcPromptInput,
33
+ attachmentListing?: string,
30
34
  ) {
31
35
  // Resolve the consumer's base system prompt
32
36
  let basePrompt: string;
33
37
  if (typeof config.systemPrompt === "function") {
34
38
  basePrompt = await config.systemPrompt(promptContext);
35
39
  } else {
36
- basePrompt = config.systemPrompt;
40
+ basePrompt = config.systemPrompt ?? "";
37
41
  }
38
42
 
39
- const sections: string[] = [basePrompt];
43
+ const sections: string[] = basePrompt ? [basePrompt] : [];
40
44
 
41
45
  // Pre-resolved endpoints from knowledge graph
42
46
  if (resolved) {
43
47
  sections.push(buildResolvedSection(resolved));
44
48
  }
45
49
 
50
+ // Control Center: published prompt + per-turn resolved catalog section
51
+ if (cc) {
52
+ const ccSection = buildCcSection(cc);
53
+ if (ccSection) sections.push(ccSection);
54
+ }
55
+
56
+ if (attachmentListing) {
57
+ sections.push(attachmentListing);
58
+ }
59
+
46
60
  return sections.join("\n");
47
61
  }
48
62
 
49
- // ---------------------------------------------------------------------------
50
- // Schema field type (parsed from endpoint JSON strings)
51
- // ---------------------------------------------------------------------------
52
-
53
63
  type SchemaField = {
54
64
  name: string;
55
65
  required?: boolean;
@@ -58,11 +68,7 @@ type SchemaField = {
58
68
  properties?: SchemaField[];
59
69
  };
60
70
 
61
- // ---------------------------------------------------------------------------
62
- // Layer 2: Schema compression
63
- // ---------------------------------------------------------------------------
64
-
65
- /** Compact param/body: `name?: type, nested?: {a: string, b: number}[]` */
71
+ /** Compression layer 2. Compact param/body: `name?: type, nested?: {a: string, b: number}[]` */
66
72
  function compactParamFields(fields: SchemaField[]): string {
67
73
  return fields
68
74
  .map((f) => {
@@ -109,14 +115,48 @@ function compactResponse(jsonStr: string) {
109
115
  }
110
116
  }
111
117
 
112
- // ---------------------------------------------------------------------------
113
- // Layer 1: Group endpoints by method + path
114
- // ---------------------------------------------------------------------------
115
-
118
+ /**
119
+ * Compression layer 1. Endpoints reached via several concepts arrive as
120
+ * duplicates sharing one method+path; collapsing them first means every later
121
+ * layer works on one entry per real endpoint.
122
+ */
116
123
  type GroupedEndpoint = Omit<ResolvedEndpoint, "concept"> & {
117
124
  concepts: string[];
118
125
  };
119
126
 
127
+ function addUnique<T>(list: T[], value: T, matches: (a: T, b: T) => boolean = Object.is) {
128
+ if (!list.some((item) => matches(item, value))) {
129
+ list.push(value);
130
+ }
131
+ }
132
+
133
+ /** Folds a second endpoint sharing this method and path into the group already collected. */
134
+ function mergeEndpoint(existing: GroupedEndpoint, ep: ResolvedEndpoint) {
135
+ addUnique(existing.concepts, ep.concept);
136
+
137
+ for (const rule of ep.rules) {
138
+ addUnique(existing.rules, rule);
139
+ }
140
+ for (const dep of ep.dependencies) {
141
+ addUnique(
142
+ existing.dependencies,
143
+ dep,
144
+ (a, b) => a.depPath === b.depPath && a.paramName === b.paramName,
145
+ );
146
+ }
147
+ }
148
+
149
+ /** The arrays are copied because merging mutates them, and the source endpoint is shared. */
150
+ function toGroup(ep: ResolvedEndpoint) {
151
+ const { concept, ...rest } = ep;
152
+ return {
153
+ ...rest,
154
+ concepts: [concept],
155
+ dependencies: [...ep.dependencies],
156
+ rules: [...ep.rules],
157
+ };
158
+ }
159
+
120
160
  function groupEndpointsBySignature(endpoints: ResolvedEndpoint[]) {
121
161
  const groups = new Map<string, GroupedEndpoint>();
122
162
 
@@ -125,46 +165,19 @@ function groupEndpointsBySignature(endpoints: ResolvedEndpoint[]) {
125
165
  const existing = groups.get(key);
126
166
 
127
167
  if (existing) {
128
- if (!existing.concepts.includes(ep.concept)) {
129
- existing.concepts.push(ep.concept);
130
- }
131
- for (const rule of ep.rules) {
132
- if (!existing.rules.includes(rule)) {
133
- existing.rules.push(rule);
134
- }
135
- }
136
- for (const dep of ep.dependencies) {
137
- const isDuplicate = existing.dependencies.some(
138
- (d) => d.depPath === dep.depPath && d.paramName === dep.paramName,
139
- );
140
- if (!isDuplicate) {
141
- existing.dependencies.push(dep);
142
- }
143
- }
168
+ mergeEndpoint(existing, ep);
144
169
  } else {
145
- groups.set(key, {
146
- concepts: [ep.concept],
147
- relation: ep.relation,
148
- name: ep.name,
149
- path: ep.path,
150
- method: ep.method,
151
- params: ep.params,
152
- body: ep.body,
153
- response: ep.response,
154
- dependencies: [...ep.dependencies],
155
- rules: [...ep.rules],
156
- metadata: ep.metadata,
157
- });
170
+ groups.set(key, toGroup(ep));
158
171
  }
159
172
  }
160
173
 
161
174
  return Array.from(groups.values());
162
175
  }
163
176
 
164
- // ---------------------------------------------------------------------------
165
- // Layer 3: Extract shared rules into a global section
166
- // ---------------------------------------------------------------------------
167
-
177
+ /**
178
+ * Compression layer 3. Hoists rules repeated across endpoints into one global
179
+ * section, so a rule governing twenty endpoints is stated once, not twenty times.
180
+ */
168
181
  function extractSharedRules(groups: GroupedEndpoint[], services: ResolvedService[]) {
169
182
  const ruleCounts = new Map<string, number>();
170
183
 
@@ -198,16 +211,16 @@ function extractSharedRules(groups: GroupedEndpoint[], services: ResolvedService
198
211
  };
199
212
  }
200
213
 
201
- // ---------------------------------------------------------------------------
202
- // Layer 4: Deduplicate identical response schemas across endpoints
203
- // ---------------------------------------------------------------------------
204
-
214
+ /**
215
+ * Compression layer 4. Endpoints returning an identical response schema get one
216
+ * named shape definition and a reference each, instead of repeating the schema.
217
+ */
205
218
  type ResponseShapeRefs = {
206
219
  shapeDefs: { name: string; content: string }[];
207
220
  refMap: Map<string, string>;
208
221
  };
209
222
 
210
- function buildResponseShapeRefs(groups: GroupedEndpoint[]): ResponseShapeRefs {
223
+ function buildResponseShapeRefs(groups: GroupedEndpoint[]) {
211
224
  // Key on the raw JSON string (byte-identical for endpoints sharing the same
212
225
  // Endpoint node in Neo4j). Fall back to the compact string for cases where
213
226
  // different raw JSON produces the same compact shape.
@@ -258,9 +271,50 @@ function buildResponseShapeRefs(groups: GroupedEndpoint[]): ResponseShapeRefs {
258
271
  return { shapeDefs, refMap };
259
272
  }
260
273
 
261
- // ---------------------------------------------------------------------------
262
- // Pre-resolved section builder
263
- // ---------------------------------------------------------------------------
274
+ /** A heading and its lines, or nothing at all when there are no lines to show. */
275
+ function renderSection(heading: string, lines: string[]) {
276
+ if (lines.length === 0) return [];
277
+ return [`\n### ${heading}`, ...lines.map((line) => `\n${line}`)];
278
+ }
279
+
280
+ function renderEndpoint(ep: GroupedEndpoint, refMap: ResponseShapeRefs["refMap"]) {
281
+ const compactResp = compactResponse(ep.response);
282
+ const body = compactParams(ep.body);
283
+
284
+ const lines = [
285
+ `\n### ${ep.name} — ${ep.method} ${ep.path} (${ep.relation})`,
286
+ `\n- Concepts: ${ep.concepts.join(", ")}`,
287
+ `\n- Params: ${compactParams(ep.params)}`,
288
+ body === "(none)" ? "" : `\n- Body: ${body}`,
289
+ `\n- Response: ${refMap.get(compactResp) ?? compactResp}`,
290
+ ep.rules.length > 0 ? `\n Rules: ${ep.rules.join("; ")}` : "",
291
+ renderDependencies(ep.dependencies),
292
+ ep.metadata === "{}" ? "" : `\n Metadata: ${ep.metadata}`,
293
+ ];
294
+
295
+ return lines.join("");
296
+ }
297
+
298
+ function renderDependencies(dependencies: GroupedEndpoint["dependencies"]) {
299
+ if (dependencies.length === 0) return "";
300
+
301
+ const calls = dependencies.map(
302
+ (d) =>
303
+ ` - Call ${d.depMethod} ${d.depPath} first → use its "${d.fromField}" as "${d.paramName}"`,
304
+ );
305
+ return `\n Dependencies:\n${calls.join("\n")}`;
306
+ }
307
+
308
+ function renderService(svc: ResolvedService) {
309
+ const rules = svc.rules.length > 0 ? `\n Rules: ${svc.rules.join("; ")}` : "";
310
+ const meta = svc.metadata === "{}" ? "" : `\n- Metadata: ${svc.metadata}`;
311
+
312
+ return (
313
+ `\n### ${svc.concept} via ${svc.serviceName} (service)` +
314
+ `\n- Built-in ID: ${svc.builtInId}` +
315
+ `\n- Description: ${svc.description || "N/A"}${rules}${meta}`
316
+ );
317
+ }
264
318
 
265
319
  function buildResolvedSection(resolved: ResolvedContext) {
266
320
  const allEndpoints = [...resolved.readEndpoints, ...resolved.writeEndpoints];
@@ -282,73 +336,20 @@ function buildResolvedSection(resolved: ResolvedContext) {
282
336
  // Layer 4: deduplicate identical response schemas
283
337
  const { shapeDefs, refMap } = buildResponseShapeRefs(cleanedGroups);
284
338
 
285
- const parts: string[] = [
339
+ return [
286
340
  `
287
341
  ## Pre-resolved API Endpoints
288
342
  The following endpoints were automatically matched to the user's message.`,
289
- ];
290
-
291
- // Shared rules
292
- if (sharedRules.length > 0) {
293
- parts.push("\n### General Rules");
294
- for (const rule of sharedRules) {
295
- parts.push(`\n- ${rule}`);
296
- }
297
- }
298
-
299
- // Response shape definitions
300
- if (shapeDefs.length > 0) {
301
- parts.push("\n### Response Shapes");
302
- for (const def of shapeDefs) {
303
- parts.push(`\n${def.name}: ${def.content}`);
304
- }
305
- }
306
-
307
- // Endpoints (Layer 2: compact schemas)
308
- for (const ep of cleanedGroups) {
309
- const concepts = ep.concepts.join(", ");
310
- const params = compactParams(ep.params);
311
- const body = compactParams(ep.body);
312
- const compactResp = compactResponse(ep.response);
313
- const response = refMap.get(compactResp) ?? compactResp;
314
-
315
- const rules = ep.rules.length > 0 ? `\n Rules: ${ep.rules.join("; ")}` : "";
316
- const deps =
317
- ep.dependencies.length > 0
318
- ? "\n Dependencies:\n" +
319
- ep.dependencies
320
- .map(
321
- (d) =>
322
- ` - Call ${d.depMethod} ${d.depPath} first → use its "${d.fromField}" as "${d.paramName}"`,
323
- )
324
- .join("\n")
325
- : "";
326
- const meta = ep.metadata !== "{}" ? `\n Metadata: ${ep.metadata}` : "";
327
-
328
- let block = `\n### ${ep.name} — ${ep.method} ${ep.path} (${ep.relation})`;
329
- block += `\n- Concepts: ${concepts}`;
330
- block += `\n- Params: ${params}`;
331
- if (body !== "(none)") {
332
- block += `\n- Body: ${body}`;
333
- }
334
- block += `\n- Response: ${response}`;
335
- block += rules;
336
- block += deps;
337
- block += meta;
338
-
339
- parts.push(block);
340
- }
341
-
342
- // Services
343
- for (const svc of cleanedServices) {
344
- const rules = svc.rules.length > 0 ? `\n Rules: ${svc.rules.join("; ")}` : "";
345
- const meta = svc.metadata !== "{}" ? `\n- Metadata: ${svc.metadata}` : "";
346
- parts.push(
347
- `\n### ${svc.concept} via ${svc.serviceName} (service)` +
348
- `\n- Built-in ID: ${svc.builtInId}` +
349
- `\n- Description: ${svc.description || "N/A"}${rules}${meta}`,
350
- );
351
- }
352
-
353
- return parts.join("");
343
+ ...renderSection(
344
+ "General Rules",
345
+ sharedRules.map((rule) => `- ${rule}`),
346
+ ),
347
+ ...renderSection(
348
+ "Response Shapes",
349
+ shapeDefs.map((def) => `${def.name}: ${def.content}`),
350
+ ),
351
+ // Layer 2: compact schemas
352
+ ...cleanedGroups.map((ep) => renderEndpoint(ep, refMap)),
353
+ ...cleanedServices.map(renderService),
354
+ ].join("");
354
355
  }