@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.
- package/README.md +8 -3
- package/contracts/README.md +23 -0
- package/contracts/graph/embed.ts +50 -0
- package/{src/lib → contracts}/graph/helpers.ts +4 -10
- package/{src/lib → contracts}/graph/neo4j.ts +14 -27
- package/contracts/graph/schema.ts +65 -0
- package/{src/lib → contracts}/graph/types.ts +2 -29
- package/contracts/graph.ts +36 -0
- package/contracts/rich-text.ts +207 -0
- package/contracts/runtime.ts +243 -0
- package/contracts/wire.ts +143 -0
- package/dist/contracts/graph/embed.d.ts +22 -0
- package/dist/{src/lib → contracts}/graph/helpers.d.ts +16 -14
- package/dist/{src/lib → contracts}/graph/neo4j.d.ts +5 -5
- package/dist/contracts/graph/schema.d.ts +62 -0
- package/dist/{src/lib → contracts}/graph/types.d.ts +1 -1
- package/dist/contracts/graph.d.ts +14 -0
- package/dist/contracts/rich-text.d.ts +32 -0
- package/dist/contracts/runtime.d.ts +310 -0
- package/dist/contracts/wire.d.ts +120 -0
- package/dist/src/lib/adapters/database/index.d.ts +61 -0
- package/dist/src/lib/adapters/database/message-content.d.ts +30 -0
- package/dist/src/lib/adapters/database/mssql/attachments.d.ts +100 -0
- package/dist/src/lib/adapters/database/mssql/client.d.ts +8 -0
- package/dist/src/lib/adapters/database/mssql/index.d.ts +194 -0
- package/dist/src/lib/adapters/database/mssql/llm-requests.d.ts +17 -0
- package/dist/src/lib/adapters/database/mssql/messages.d.ts +37 -0
- package/dist/src/lib/adapters/database/mssql/threads.d.ts +50 -0
- package/dist/src/lib/adapters/database/postgres/attachments.d.ts +113 -0
- package/dist/src/lib/adapters/database/postgres/client.d.ts +8 -0
- package/dist/src/lib/adapters/database/postgres/index.d.ts +207 -0
- package/dist/src/lib/adapters/database/postgres/llm-requests.d.ts +17 -0
- package/dist/src/lib/adapters/database/postgres/messages.d.ts +37 -0
- package/dist/src/lib/adapters/database/postgres/threads.d.ts +50 -0
- package/{src/lib/adapters/storage.ts → dist/src/lib/adapters/storage/index.d.ts} +1 -1
- package/dist/src/lib/adapters/{minio.d.ts → storage/minio.d.ts} +1 -1
- package/dist/src/lib/ai/active-runs.d.ts +63 -0
- package/dist/src/lib/ai/attachments.d.ts +30 -0
- package/dist/src/lib/ai/backend-url.d.ts +16 -0
- package/dist/src/lib/ai/cc-runtime.d.ts +61 -0
- package/dist/src/lib/ai/commit-gate.d.ts +21 -0
- package/dist/src/lib/ai/context/builder.d.ts +6 -7
- package/dist/src/lib/ai/context/compression-middleware.d.ts +15 -0
- package/dist/src/lib/ai/context/compressor.d.ts +2 -13
- package/dist/src/lib/ai/context/intra-turn-compressor.d.ts +9 -9
- package/dist/src/lib/ai/context/optimize-thread-context.d.ts +9 -0
- package/dist/src/lib/ai/context/summarizer.d.ts +3 -3
- package/dist/src/lib/ai/context/token-estimator.d.ts +5 -8
- package/dist/src/lib/ai/fetch.d.ts +1 -1
- package/dist/src/lib/ai/finish-turn.d.ts +23 -0
- package/dist/src/lib/ai/helpers.d.ts +37 -4
- package/dist/src/lib/ai/index.d.ts +6 -3
- package/dist/src/lib/ai/inspector.d.ts +41 -0
- package/dist/src/lib/ai/interceptors/request-interceptor.d.ts +6 -5
- package/dist/src/lib/ai/prompt.d.ts +5 -4
- package/dist/src/lib/ai/redis-runs.d.ts +41 -0
- package/dist/src/lib/ai/redis-stream-log.d.ts +39 -0
- package/dist/src/lib/ai/tools/execute-code.tool.d.ts +18 -4
- package/dist/src/lib/ai/tools/query-graph.tool.d.ts +13 -5
- package/dist/src/lib/ai/tools/read-attachment.tool.d.ts +21 -0
- package/dist/src/lib/ai/tools/search-common.d.ts +17 -0
- package/dist/src/lib/ai/tools/search-knowledge.tool.d.ts +15 -0
- package/dist/src/lib/ai/tools/search-services.tool.d.ts +12 -0
- package/dist/src/lib/ai/tools/search-tools.tool.d.ts +12 -0
- package/dist/src/lib/ai/turn-tools.d.ts +39 -0
- package/dist/src/lib/ai/vision/rasterize-pdf.d.ts +26 -0
- package/dist/src/lib/ai/vision/rasterize-pdf.worker.d.ts +1 -0
- package/dist/src/lib/ai/vision/vision-reader.d.ts +45 -0
- package/dist/src/lib/cc/client.d.ts +183 -0
- package/dist/src/lib/cc/config-cache.d.ts +20 -0
- package/dist/src/lib/cc/format.d.ts +23 -0
- package/dist/src/lib/cc/registry.d.ts +34 -0
- package/dist/src/lib/cc/types.d.ts +27 -0
- package/dist/src/lib/config.d.ts +81 -64
- package/dist/src/lib/db/drizzle.config.mssql.d.ts +2 -0
- package/dist/src/lib/db/drizzle.config.pg.d.ts +2 -0
- package/dist/src/lib/db/migrate.d.ts +7 -1
- package/dist/src/lib/db/{schema.d.ts → schema.mssql.d.ts} +138 -29
- package/dist/src/lib/db/schema.pg.d.ts +546 -0
- package/dist/src/lib/factory.d.ts +2 -12
- package/dist/src/lib/graph/index.d.ts +10 -11
- package/dist/src/lib/graph/resolver.d.ts +2 -3
- package/dist/src/lib/index.d.ts +3 -3
- package/dist/src/lib/redis.d.ts +19 -0
- package/dist/src/lib/routes/chat.d.ts +1 -1
- package/dist/src/lib/routes/files.d.ts +1 -1
- package/dist/src/lib/routes/owned-thread.d.ts +17 -0
- package/dist/src/lib/routes/threads.d.ts +1 -1
- package/dist/src/lib/routes/ws.d.ts +1 -1
- package/dist/src/lib/types.d.ts +20 -37
- package/dist/src/lib/ws/connections.d.ts +2 -1
- package/package.json +33 -18
- package/src/lib/adapters/database/index.ts +78 -0
- package/src/lib/adapters/database/message-content.ts +39 -0
- package/src/lib/adapters/database/mssql/attachments.ts +90 -0
- package/src/lib/adapters/database/mssql/client.ts +11 -0
- package/src/lib/adapters/database/mssql/index.ts +23 -0
- package/src/lib/adapters/database/mssql/llm-requests.ts +43 -0
- package/src/lib/adapters/database/mssql/messages.ts +92 -0
- package/src/lib/adapters/database/mssql/threads.ts +83 -0
- package/src/lib/adapters/database/postgres/attachments.ts +88 -0
- package/src/lib/adapters/database/postgres/client.ts +11 -0
- package/src/lib/adapters/database/postgres/index.ts +23 -0
- package/src/lib/adapters/database/postgres/llm-requests.ts +45 -0
- package/src/lib/adapters/database/postgres/messages.ts +92 -0
- package/src/lib/adapters/database/postgres/threads.ts +84 -0
- package/{dist/src/lib/adapters/storage.d.ts → src/lib/adapters/storage/index.ts} +1 -1
- package/src/lib/adapters/{minio.ts → storage/minio.ts} +5 -5
- package/src/lib/ai/active-runs.ts +157 -0
- package/src/lib/ai/attachments.ts +144 -0
- package/src/lib/ai/backend-url.ts +27 -0
- package/src/lib/ai/cc-runtime.ts +63 -0
- package/src/lib/ai/commit-gate.ts +116 -0
- package/src/lib/ai/context/builder.ts +12 -14
- package/src/lib/ai/context/compression-middleware.ts +44 -0
- package/src/lib/ai/context/compressor.ts +67 -59
- package/src/lib/ai/context/intra-turn-compressor.ts +121 -204
- package/src/lib/ai/context/optimize-thread-context.ts +50 -0
- package/src/lib/ai/context/summarizer.ts +28 -30
- package/src/lib/ai/context/token-estimator.ts +35 -30
- package/src/lib/ai/fetch.ts +10 -5
- package/src/lib/ai/finish-turn.ts +75 -0
- package/src/lib/ai/helpers.ts +83 -15
- package/src/lib/ai/index.ts +366 -329
- package/src/lib/ai/inspector.ts +112 -0
- package/src/lib/ai/interceptors/request-interceptor.ts +70 -42
- package/src/lib/ai/prompt.ts +126 -125
- package/src/lib/ai/redis-runs.ts +167 -0
- package/src/lib/ai/redis-stream-log.ts +219 -0
- package/src/lib/ai/tools/execute-code.tool.ts +178 -67
- package/src/lib/ai/tools/query-graph.tool.ts +7 -8
- package/src/lib/ai/tools/read-attachment.tool.ts +59 -0
- package/src/lib/ai/tools/search-common.ts +15 -0
- package/src/lib/ai/tools/search-knowledge.tool.ts +33 -0
- package/src/lib/ai/tools/search-services.tool.ts +31 -0
- package/src/lib/ai/tools/search-tools.tool.ts +29 -0
- package/src/lib/ai/turn-tools.ts +154 -0
- package/src/lib/ai/vision/rasterize-pdf.ts +69 -0
- package/src/lib/ai/vision/rasterize-pdf.worker.ts +81 -0
- package/src/lib/ai/vision/vision-reader.ts +130 -0
- package/src/lib/auth/middleware.ts +5 -3
- package/src/lib/cc/client.ts +273 -0
- package/src/lib/cc/config-cache.ts +32 -0
- package/src/lib/cc/format.ts +92 -0
- package/src/lib/cc/registry.ts +62 -0
- package/src/lib/cc/types.ts +44 -0
- package/src/lib/config.ts +102 -71
- package/src/lib/db/drizzle.config.mssql.ts +9 -0
- package/src/lib/db/drizzle.config.pg.ts +9 -0
- package/src/lib/db/migrate.ts +45 -10
- package/src/lib/db/migrations/mssql/20260729092726_talented_wilson_fisk/migration.sql +20 -0
- package/src/lib/db/migrations/mssql/20260729092726_talented_wilson_fisk/snapshot.json +497 -0
- package/src/lib/db/migrations/mssql/20260801003652_perpetual_blue_shield/migration.sql +1 -0
- package/src/lib/db/migrations/mssql/20260801003652_perpetual_blue_shield/snapshot.json +516 -0
- package/src/lib/db/migrations/mssql/20260812174642_user_id_text/migration.sql +2 -0
- package/src/lib/db/migrations/mssql/20260812174642_user_id_text/snapshot.json +516 -0
- package/src/lib/db/migrations/pg/20260801084117_thick_ben_grimm/migration.sql +53 -0
- package/src/lib/db/migrations/pg/20260801084117_thick_ben_grimm/snapshot.json +584 -0
- package/src/lib/db/migrations/pg/20260812174622_user_id_text/migration.sql +2 -0
- package/src/lib/db/migrations/pg/20260812174622_user_id_text/snapshot.json +584 -0
- package/src/lib/db/{schema.ts → schema.mssql.ts} +29 -18
- package/src/lib/db/schema.pg.ts +95 -0
- package/src/lib/factory.ts +44 -89
- package/src/lib/graph/index.ts +12 -40
- package/src/lib/graph/resolver.ts +146 -116
- package/src/lib/index.ts +11 -4
- package/src/lib/redis.ts +44 -0
- package/src/lib/routes/chat.ts +91 -62
- package/src/lib/routes/files.ts +105 -83
- package/src/lib/routes/owned-thread.ts +17 -0
- package/src/lib/routes/threads.ts +14 -30
- package/src/lib/routes/ws.ts +9 -3
- package/src/lib/types.ts +37 -36
- package/src/lib/ws/connections.ts +9 -1
- package/tsconfig.json +48 -0
- package/dist/src/lib/adapters/database.d.ts +0 -45
- package/dist/src/lib/adapters/mssql.d.ts +0 -3
- package/dist/src/lib/ai/active-streams.d.ts +0 -14
- package/dist/src/lib/ai/context/index.d.ts +0 -16
- package/dist/src/lib/ai/tools/capture-files.tool.d.ts +0 -6
- package/dist/src/lib/cli/extract-endpoints.d.ts +0 -6
- package/dist/src/lib/graph/expand-domains.d.ts +0 -2
- package/dist/src/lib/graph/generate-cypher.d.ts +0 -22
- package/dist/src/lib/graph/seed.d.ts +0 -19
- package/dist/src/lib/graph/validate.d.ts +0 -2
- package/dist/src/lib/routes/index.d.ts +0 -4
- package/dist/src/lib/ws/events.d.ts +0 -39
- package/dist/src/lib/ws/index.d.ts +0 -3
- package/dist/src/lib/ws/notify.d.ts +0 -2
- package/src/lib/adapters/database.ts +0 -48
- package/src/lib/adapters/mssql.ts +0 -231
- package/src/lib/ai/active-streams.ts +0 -123
- package/src/lib/ai/context/index.ts +0 -80
- package/src/lib/ai/tools/capture-files.tool.ts +0 -20
- package/src/lib/cli/extract-endpoints.ts +0 -550
- package/src/lib/graph/expand-domains.ts +0 -276
- package/src/lib/graph/generate-cypher.ts +0 -192
- package/src/lib/graph/seed.ts +0 -162
- package/src/lib/graph/validate.ts +0 -78
- package/src/lib/routes/index.ts +0 -4
- package/src/lib/ws/events.ts +0 -39
- package/src/lib/ws/index.ts +0 -11
- package/src/lib/ws/notify.ts +0 -9
- package/src/sample/db/client.ts +0 -9
- package/src/sample/db/migrations/20260411023125_rich_purple_man/migration.sql +0 -5
- package/src/sample/db/migrations/20260411023125_rich_purple_man/snapshot.json +0 -50
- package/src/sample/db/schema.ts +0 -10
- package/src/sample/domains/account/concepts/session.concept.ts +0 -17
- package/src/sample/domains/account/endpoints/listCurrentSessions.endpoint.ts +0 -31
- package/src/sample/domains/account/endpoints/revokeAllOtherSessions.endpoint.ts +0 -22
- package/src/sample/domains/account/endpoints/revokeCurrentSession.endpoint.ts +0 -33
- package/src/sample/domains/account/index.ts +0 -18
- package/src/sample/domains/appraisals/concepts/appraisalCycle.concept.ts +0 -15
- package/src/sample/domains/appraisals/concepts/appraisalRecord.concept.ts +0 -20
- package/src/sample/domains/appraisals/concepts/appraisalRecordCompetency.concept.ts +0 -10
- package/src/sample/domains/appraisals/concepts/appraisalRecordFunctionalRequirement.concept.ts +0 -10
- package/src/sample/domains/appraisals/concepts/appraisalRecordGoal.concept.ts +0 -17
- package/src/sample/domains/appraisals/endpoints/getAppraisalRecordById.endpoint.ts +0 -321
- package/src/sample/domains/appraisals/endpoints/getAppraisalRecordCompetencies.endpoint.ts +0 -120
- package/src/sample/domains/appraisals/endpoints/getAppraisalRecordFunctionalRequirements.endpoint.ts +0 -126
- package/src/sample/domains/appraisals/endpoints/getAppraisalRecordGoals.endpoint.ts +0 -104
- package/src/sample/domains/appraisals/endpoints/getAppraisalRecordScore.endpoint.ts +0 -58
- package/src/sample/domains/appraisals/endpoints/listAppraisalCyclesSimple.endpoint.ts +0 -52
- package/src/sample/domains/appraisals/endpoints/listAppraisalRecords.endpoint.ts +0 -245
- package/src/sample/domains/appraisals/endpoints/listAppraisalTemplatesSimple.endpoint.ts +0 -52
- package/src/sample/domains/appraisals/index.ts +0 -40
- package/src/sample/domains/appraisals/rules/appraisalRecordScoping.rule.ts +0 -7
- package/src/sample/domains/attendance/concepts/attendancePermission.concept.ts +0 -17
- package/src/sample/domains/attendance/concepts/attendanceTransaction.concept.ts +0 -17
- package/src/sample/domains/attendance/concepts/publicHoliday.concept.ts +0 -10
- package/src/sample/domains/attendance/concepts/punch.concept.ts +0 -19
- package/src/sample/domains/attendance/endpoints/getAttendanceTransactionById.endpoint.ts +0 -444
- package/src/sample/domains/attendance/endpoints/getCurrentAttendanceProfile.endpoint.ts +0 -886
- package/src/sample/domains/attendance/endpoints/getCurrentAttendanceStatistics.endpoint.ts +0 -49
- package/src/sample/domains/attendance/endpoints/listAttendancePermissions.endpoint.ts +0 -176
- package/src/sample/domains/attendance/endpoints/listAttendanceTransactionStates.endpoint.ts +0 -26
- package/src/sample/domains/attendance/endpoints/listAttendanceTransactions.endpoint.ts +0 -373
- package/src/sample/domains/attendance/endpoints/listPublicHolidaysSimple.endpoint.ts +0 -52
- package/src/sample/domains/attendance/endpoints/listPunchTypes.endpoint.ts +0 -25
- package/src/sample/domains/attendance/endpoints/listPunches.endpoint.ts +0 -178
- package/src/sample/domains/attendance/index.ts +0 -41
- package/src/sample/domains/attendance/services/attendancePermissions.service.ts +0 -15
- package/src/sample/domains/employees/concepts/employee.concept.ts +0 -20
- package/src/sample/domains/employees/concepts/employeeBankAccount.concept.ts +0 -19
- package/src/sample/domains/employees/concepts/employeeChild.concept.ts +0 -19
- package/src/sample/domains/employees/concepts/employeeDocument.concept.ts +0 -21
- package/src/sample/domains/employees/concepts/employeeEvent.concept.ts +0 -21
- package/src/sample/domains/employees/concepts/employeeExperience.concept.ts +0 -18
- package/src/sample/domains/employees/concepts/employeeJobLevelChange.concept.ts +0 -21
- package/src/sample/domains/employees/concepts/employeeMedal.concept.ts +0 -20
- package/src/sample/domains/employees/concepts/employeeQualification.concept.ts +0 -20
- package/src/sample/domains/employees/concepts/employeeSpouse.concept.ts +0 -21
- package/src/sample/domains/employees/concepts/employeeViolation.concept.ts +0 -19
- package/src/sample/domains/employees/endpoints/getCurrentEmployee.endpoint.ts +0 -1651
- package/src/sample/domains/employees/endpoints/getCurrentIdentity.endpoint.ts +0 -197
- package/src/sample/domains/employees/endpoints/getCurrentManagers.endpoint.ts +0 -142
- package/src/sample/domains/employees/endpoints/getEmployeeById.endpoint.ts +0 -1659
- package/src/sample/domains/employees/endpoints/getEmployeeStatistics.endpoint.ts +0 -43
- package/src/sample/domains/employees/endpoints/listBankAccounts.endpoint.ts +0 -223
- package/src/sample/domains/employees/endpoints/listChildren.endpoint.ts +0 -211
- package/src/sample/domains/employees/endpoints/listDocuments.endpoint.ts +0 -222
- package/src/sample/domains/employees/endpoints/listEmployeesSimple.endpoint.ts +0 -156
- package/src/sample/domains/employees/endpoints/listEvents.endpoint.ts +0 -120
- package/src/sample/domains/employees/endpoints/listExperiences.endpoint.ts +0 -188
- package/src/sample/domains/employees/endpoints/listJobLevelChanges.endpoint.ts +0 -240
- package/src/sample/domains/employees/endpoints/listMedals.endpoint.ts +0 -266
- package/src/sample/domains/employees/endpoints/listQualifications.endpoint.ts +0 -265
- package/src/sample/domains/employees/endpoints/listSpouses.endpoint.ts +0 -278
- package/src/sample/domains/employees/endpoints/listViolations.endpoint.ts +0 -245
- package/src/sample/domains/employees/index.ts +0 -75
- package/src/sample/domains/employees/services/employees.service.ts +0 -181
- package/src/sample/domains/index.ts +0 -10
- package/src/sample/domains/leaves/concepts/leave.concept.ts +0 -21
- package/src/sample/domains/leaves/concepts/leaveBalance.concept.ts +0 -17
- package/src/sample/domains/leaves/concepts/leaveBalanceTransaction.concept.ts +0 -16
- package/src/sample/domains/leaves/concepts/leaveType.concept.ts +0 -13
- package/src/sample/domains/leaves/concepts/leaveTypes.concept.ts +0 -205
- package/src/sample/domains/leaves/endpoints/getBalance.endpoint.ts +0 -53
- package/src/sample/domains/leaves/endpoints/getLeaveById.endpoint.ts +0 -53
- package/src/sample/domains/leaves/endpoints/listBalanceTransactions.endpoint.ts +0 -196
- package/src/sample/domains/leaves/endpoints/listBalanceTypes.endpoint.ts +0 -26
- package/src/sample/domains/leaves/endpoints/listBalances.endpoint.ts +0 -201
- package/src/sample/domains/leaves/endpoints/listLeaveTypes.endpoint.ts +0 -28
- package/src/sample/domains/leaves/endpoints/listLeaves.endpoint.ts +0 -234
- package/src/sample/domains/leaves/index.ts +0 -38
- package/src/sample/domains/leaves/services/leaveRequests.service.ts +0 -232
- package/src/sample/domains/notifications/concepts/notification.concept.ts +0 -19
- package/src/sample/domains/notifications/endpoints/countMyNotifications.endpoint.ts +0 -21
- package/src/sample/domains/notifications/endpoints/getMyNotification.endpoint.ts +0 -57
- package/src/sample/domains/notifications/endpoints/listMyNotifications.endpoint.ts +0 -59
- package/src/sample/domains/notifications/endpoints/markMyNotificationAsRead.endpoint.ts +0 -32
- package/src/sample/domains/notifications/index.ts +0 -20
- package/src/sample/domains/payroll/concepts/payslip.concept.ts +0 -18
- package/src/sample/domains/payroll/concepts/salaryCertificate.concept.ts +0 -17
- package/src/sample/domains/payroll/concepts/salaryCertificateRequestingEntity.concept.ts +0 -8
- package/src/sample/domains/payroll/endpoints/getPayslipById.endpoint.ts +0 -238
- package/src/sample/domains/payroll/endpoints/listPayslips.endpoint.ts +0 -216
- package/src/sample/domains/payroll/endpoints/listSalaryCertificateLanguages.endpoint.ts +0 -25
- package/src/sample/domains/payroll/endpoints/listSalaryCertificateRequestingEntities.endpoint.ts +0 -62
- package/src/sample/domains/payroll/endpoints/listSalaryCertificateTypes.endpoint.ts +0 -24
- package/src/sample/domains/payroll/endpoints/listSalaryCertificates.endpoint.ts +0 -122
- package/src/sample/domains/payroll/endpoints/previewSalaryCertificate.endpoint.ts +0 -45
- package/src/sample/domains/payroll/index.ts +0 -32
- package/src/sample/domains/payroll/rules/payrollEmployeeContext.rule.ts +0 -7
- package/src/sample/domains/payroll/services/salaryCertificates.service.ts +0 -15
- package/src/sample/domains/servicing/concepts/service.concept.ts +0 -6
- package/src/sample/domains/servicing/concepts/serviceRequest.concept.ts +0 -12
- package/src/sample/domains/servicing/concepts/serviceRequestApproval.concept.ts +0 -9
- package/src/sample/domains/servicing/endpoints/cancelServiceRequest.endpoint.ts +0 -21
- package/src/sample/domains/servicing/endpoints/createServiceRequest.endpoint.ts +0 -511
- package/src/sample/domains/servicing/endpoints/getServiceRequest.endpoint.ts +0 -352
- package/src/sample/domains/servicing/endpoints/getServiceRequestFormItems.endpoint.ts +0 -219
- package/src/sample/domains/servicing/endpoints/getServiceRequestTransactionFormItems.endpoint.ts +0 -216
- package/src/sample/domains/servicing/endpoints/getServiceStates.endpoint.ts +0 -47
- package/src/sample/domains/servicing/endpoints/invokeServiceRequestAction.endpoint.ts +0 -139
- package/src/sample/domains/servicing/endpoints/listServiceRequests.endpoint.ts +0 -292
- package/src/sample/domains/servicing/endpoints/listServices.endpoint.ts +0 -108
- package/src/sample/domains/servicing/endpoints/updateServiceRequest.endpoint.ts +0 -355
- package/src/sample/domains/servicing/index.ts +0 -44
- package/src/sample/domains/servicing/rules/checkValidActions.rule.ts +0 -7
- package/src/sample/domains/servicing/rules/createServiceRequest.rule.ts +0 -7
- package/src/sample/domains/servicing/rules/filterServiceRequestsByState.rule.ts +0 -7
- package/src/sample/domains/servicing/rules/passingOptionFields.rule.ts +0 -7
- package/src/sample/domains/shared/rules/pagination.rule.ts +0 -7
- package/src/sample/domains/suggestions/concepts/suggestion.concept.ts +0 -19
- package/src/sample/domains/suggestions/concepts/suggestionCategory.concept.ts +0 -7
- package/src/sample/domains/suggestions/concepts/suggestionImpactLevel.concept.ts +0 -7
- package/src/sample/domains/suggestions/endpoints/createSuggestion.endpoint.ts +0 -705
- package/src/sample/domains/suggestions/endpoints/deleteSuggestion.endpoint.ts +0 -32
- package/src/sample/domains/suggestions/endpoints/getSuggestionById.endpoint.ts +0 -635
- package/src/sample/domains/suggestions/endpoints/listSuggestionCategories.endpoint.ts +0 -62
- package/src/sample/domains/suggestions/endpoints/listSuggestionImpactLevels.endpoint.ts +0 -62
- package/src/sample/domains/suggestions/endpoints/listSuggestionStates.endpoint.ts +0 -24
- package/src/sample/domains/suggestions/endpoints/listSuggestions.endpoint.ts +0 -132
- package/src/sample/domains/suggestions/endpoints/updateSuggestion.endpoint.ts +0 -690
- package/src/sample/domains/suggestions/endpoints/updateSuggestionState.endpoint.ts +0 -39
- package/src/sample/domains/suggestions/index.ts +0 -34
- package/src/sample/domains/suggestions/rules/suggestionScope.rule.ts +0 -7
- package/src/sample/domains/surveys/concepts/survey.concept.ts +0 -10
- package/src/sample/domains/surveys/concepts/surveyResponse.concept.ts +0 -14
- package/src/sample/domains/surveys/endpoints/getSurveyResponseById.endpoint.ts +0 -131
- package/src/sample/domains/surveys/endpoints/getTargetedSurvey.endpoint.ts +0 -129
- package/src/sample/domains/surveys/endpoints/listTargetedSurveys.endpoint.ts +0 -160
- package/src/sample/domains/surveys/endpoints/respondToSurvey.endpoint.ts +0 -144
- package/src/sample/domains/surveys/index.ts +0 -21
- package/src/sample/drizzle.config.ts +0 -11
- package/src/sample/index.bak.ts +0 -341
- package/src/sample/index.ts +0 -318
- package/src/sample/official-statements/defaults.ts +0 -57
- package/src/sample/official-statements/routes.ts +0 -137
- package/src/sample/official-statements/service.ts +0 -148
- package/src/sample/official-statements/types.ts +0 -23
- /package/src/lib/db/migrations/{20260326231647_nice_speedball → mssql/20260326231647_nice_speedball}/migration.sql +0 -0
- /package/src/lib/db/migrations/{20260326231647_nice_speedball → mssql/20260326231647_nice_speedball}/snapshot.json +0 -0
|
@@ -6,14 +6,23 @@
|
|
|
6
6
|
* or environment variables.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
import {
|
|
10
|
+
GRAPH_SCHEMA,
|
|
11
|
+
GRAPH_SCHEMA_VERSION,
|
|
12
|
+
type ConceptDef,
|
|
13
|
+
type EmbedFn,
|
|
14
|
+
type Neo4jClient,
|
|
15
|
+
} from "@cortex/contracts/graph";
|
|
13
16
|
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
// The graph's vocabulary, aliased short so the Cypher below still reads as Cypher.
|
|
18
|
+
const { label: L, rel: R, prop: P } = GRAPH_SCHEMA;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Seed data, not schema: the concept a project names to expose its generic
|
|
22
|
+
* service-request endpoints, which is why it stays here rather than in
|
|
23
|
+
* `schema.ts` — the seeder writes whatever concepts a domain declares.
|
|
24
|
+
*/
|
|
25
|
+
const SERVICE_REQUEST = "ServiceRequest";
|
|
17
26
|
|
|
18
27
|
export type RerankerConfig = {
|
|
19
28
|
url: string;
|
|
@@ -22,14 +31,10 @@ export type RerankerConfig = {
|
|
|
22
31
|
|
|
23
32
|
export type ResolverConfig = {
|
|
24
33
|
neo4j: Neo4jClient;
|
|
25
|
-
|
|
34
|
+
embed: EmbedFn;
|
|
26
35
|
reranker?: RerankerConfig;
|
|
27
36
|
};
|
|
28
37
|
|
|
29
|
-
// ---------------------------------------------------------------------------
|
|
30
|
-
// Result types
|
|
31
|
-
// ---------------------------------------------------------------------------
|
|
32
|
-
|
|
33
38
|
type EndpointDependency = {
|
|
34
39
|
depPath: string;
|
|
35
40
|
depMethod: string;
|
|
@@ -39,6 +44,8 @@ type EndpointDependency = {
|
|
|
39
44
|
|
|
40
45
|
type EndpointRelation = "read" | "write";
|
|
41
46
|
|
|
47
|
+
type RelationType = typeof R.queriedVia | typeof R.mutatedVia;
|
|
48
|
+
|
|
42
49
|
export type ResolvedEndpoint = {
|
|
43
50
|
concept: string;
|
|
44
51
|
relation: EndpointRelation;
|
|
@@ -68,13 +75,9 @@ export type ResolvedContext = {
|
|
|
68
75
|
services: ResolvedService[];
|
|
69
76
|
};
|
|
70
77
|
|
|
71
|
-
// ---------------------------------------------------------------------------
|
|
72
|
-
// Internal row types
|
|
73
|
-
// ---------------------------------------------------------------------------
|
|
74
|
-
|
|
75
78
|
type EndpointRow = {
|
|
76
79
|
concept: string;
|
|
77
|
-
relationType:
|
|
80
|
+
relationType: RelationType;
|
|
78
81
|
name: string;
|
|
79
82
|
path: string;
|
|
80
83
|
method: string;
|
|
@@ -95,11 +98,63 @@ type ServiceRow = {
|
|
|
95
98
|
rules: (string | null)[];
|
|
96
99
|
};
|
|
97
100
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
+
/**
|
|
102
|
+
* Cleared only by a restart, which is also the only thing that can change which
|
|
103
|
+
* schema this process reads with. A re-seed under a running server is the case
|
|
104
|
+
* this misses, and re-seeding at the same version is the overwhelmingly common one.
|
|
105
|
+
*/
|
|
106
|
+
let versionChecked = false;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* `@m6d/cortex-cli` stamps the schema version it seeded onto the graph; this reads
|
|
110
|
+
* it back before any Cypher below runs. Lazily, on the first resolve rather than at
|
|
111
|
+
* boot, so a Neo4j that happens to be down cannot stop `serve()`.
|
|
112
|
+
*/
|
|
113
|
+
async function assertGraphVersion(neo4j: Neo4jClient) {
|
|
114
|
+
if (versionChecked) return;
|
|
115
|
+
|
|
116
|
+
const rows: unknown = await neo4j
|
|
117
|
+
.query(
|
|
118
|
+
`OPTIONAL MATCH (g:${L.marker}) WITH g LIMIT 1
|
|
119
|
+
OPTIONAL MATCH (c:${L.concept})
|
|
120
|
+
RETURN g.${P.version} AS version, count(c) AS concepts`,
|
|
121
|
+
)
|
|
122
|
+
.then(JSON.parse)
|
|
123
|
+
.catch(() => undefined);
|
|
124
|
+
|
|
125
|
+
// An unreachable graph answers with an error object rather than a row array.
|
|
126
|
+
// That is the resolve's own failure to report, not schema skew.
|
|
127
|
+
if (!Array.isArray(rows)) return;
|
|
128
|
+
|
|
129
|
+
// OPTIONAL MATCH answers a missing marker with `null`, not with a missing row.
|
|
130
|
+
const { version: stamped, concepts } =
|
|
131
|
+
(rows as { version?: number | null; concepts?: number }[])[0] ?? {};
|
|
132
|
+
if (stamped === GRAPH_SCHEMA_VERSION) {
|
|
133
|
+
versionChecked = true;
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// No stamp over an empty graph is a project mid-setup (Neo4j configured, seed
|
|
138
|
+
// not yet run), not skew: resolve as the empty context it is. Not cached, so
|
|
139
|
+
// the stamp is validated as soon as a seed lands.
|
|
140
|
+
if (stamped == null && (concepts ?? 0) === 0) return;
|
|
141
|
+
|
|
142
|
+
throw new Error(
|
|
143
|
+
[
|
|
144
|
+
stamped == null
|
|
145
|
+
? `The Neo4j graph holds data but no schema stamp, and this server reads graph schema v${GRAPH_SCHEMA_VERSION}.`
|
|
146
|
+
: `The Neo4j graph was written with graph schema v${stamped}, and this server reads v${GRAPH_SCHEMA_VERSION}.`,
|
|
147
|
+
"Writer and reader disagree on the labels, relationships and property names, so retrieval would return empty or wrong results instead of failing.",
|
|
148
|
+
"Re-seed the graph with `bunx @m6d/cortex-cli graph seed`, or install the @m6d/cortex-server that matches the graph you have.",
|
|
149
|
+
].join(" "),
|
|
150
|
+
);
|
|
151
|
+
}
|
|
101
152
|
|
|
102
153
|
export async function resolveFromGraph(prompt: string, config: ResolverConfig) {
|
|
154
|
+
// Before the first query and outside the catch below: skew is invisible to
|
|
155
|
+
// every check further down, which is the whole reason it is checked here.
|
|
156
|
+
await assertGraphVersion(config.neo4j);
|
|
157
|
+
|
|
103
158
|
const empty: ResolvedContext = {
|
|
104
159
|
readEndpoints: [],
|
|
105
160
|
writeEndpoints: [],
|
|
@@ -107,16 +162,13 @@ export async function resolveFromGraph(prompt: string, config: ResolverConfig) {
|
|
|
107
162
|
};
|
|
108
163
|
|
|
109
164
|
try {
|
|
110
|
-
const
|
|
111
|
-
model: config.embeddingModel,
|
|
112
|
-
value: prompt,
|
|
113
|
-
});
|
|
165
|
+
const embedding = (await config.embed([prompt]))[0]!;
|
|
114
166
|
|
|
115
167
|
const conceptsRaw = await config.neo4j.query(
|
|
116
|
-
`CALL db.index.vector.queryNodes('
|
|
168
|
+
`CALL db.index.vector.queryNodes('${GRAPH_SCHEMA.conceptEmbeddingsIndex}', 10, $embedding)
|
|
117
169
|
YIELD node, score
|
|
118
170
|
WHERE score > 0.3
|
|
119
|
-
RETURN node.name AS name, node.description AS description, score
|
|
171
|
+
RETURN node.${P.name} AS name, node.${P.description} AS description, score
|
|
120
172
|
ORDER BY score DESC`,
|
|
121
173
|
{ embedding },
|
|
122
174
|
);
|
|
@@ -139,74 +191,55 @@ export async function resolveFromGraph(prompt: string, config: ResolverConfig) {
|
|
|
139
191
|
|
|
140
192
|
const endpointsRaw = await config.neo4j.query(
|
|
141
193
|
`UNWIND $names AS conceptName
|
|
142
|
-
MATCH (c
|
|
194
|
+
MATCH (c:${L.concept} {${P.name}: conceptName})-[:${R.specializes}*0..3]->(ancestor:${L.concept})
|
|
143
195
|
WITH conceptName, collect(DISTINCT ancestor) AS family
|
|
144
196
|
UNWIND family AS related
|
|
145
|
-
MATCH (related)-[rel
|
|
197
|
+
MATCH (related)-[rel:${R.queriedVia}|${R.mutatedVia}]->(e:${L.endpoint})
|
|
146
198
|
WITH conceptName, related, rel, e
|
|
147
|
-
OPTIONAL MATCH (e)-[d
|
|
199
|
+
OPTIONAL MATCH (e)-[d:${R.dependsOn}]->(dep:${L.endpoint})
|
|
148
200
|
WITH conceptName, related, rel, e,
|
|
149
201
|
collect(DISTINCT {
|
|
150
|
-
depPath: dep.path,
|
|
151
|
-
depMethod: dep.method,
|
|
152
|
-
paramName: d.paramName,
|
|
153
|
-
fromField: d.fromField
|
|
202
|
+
depPath: dep.${P.path},
|
|
203
|
+
depMethod: dep.${P.method},
|
|
204
|
+
paramName: d.${P.paramName},
|
|
205
|
+
fromField: d.${P.fromField}
|
|
154
206
|
}) AS dependencies
|
|
155
|
-
OPTIONAL MATCH (rEndpoint
|
|
156
|
-
OPTIONAL MATCH (rConcept
|
|
207
|
+
OPTIONAL MATCH (rEndpoint:${L.rule})-[:${R.governs}]->(e)
|
|
208
|
+
OPTIONAL MATCH (rConcept:${L.rule})-[:${R.governs}]->(related)
|
|
157
209
|
RETURN conceptName AS concept,
|
|
158
210
|
type(rel) AS relationType,
|
|
159
|
-
e.name AS name,
|
|
160
|
-
e.path AS path,
|
|
161
|
-
e.method AS method,
|
|
162
|
-
e.params AS params,
|
|
163
|
-
e.body AS body,
|
|
164
|
-
e.response AS response,
|
|
165
|
-
e.metadata AS metadata,
|
|
211
|
+
e.${P.name} AS name,
|
|
212
|
+
e.${P.path} AS path,
|
|
213
|
+
e.${P.method} AS method,
|
|
214
|
+
e.${P.params} AS params,
|
|
215
|
+
e.${P.body} AS body,
|
|
216
|
+
e.${P.response} AS response,
|
|
217
|
+
e.${P.metadata} AS metadata,
|
|
166
218
|
dependencies,
|
|
167
|
-
collect(DISTINCT rEndpoint.description) +
|
|
168
|
-
collect(DISTINCT rConcept.description) AS rules`,
|
|
219
|
+
collect(DISTINCT rEndpoint.${P.description}) +
|
|
220
|
+
collect(DISTINCT rConcept.${P.description}) AS rules`,
|
|
169
221
|
{ names: conceptNames },
|
|
170
222
|
);
|
|
171
223
|
|
|
172
224
|
const endpointRows = asArray<EndpointRow>(JSON.parse(endpointsRaw));
|
|
173
|
-
const allEndpoints = dedupeEndpoints(
|
|
174
|
-
endpointRows.map(function (row) {
|
|
175
|
-
return {
|
|
176
|
-
concept: row.concept,
|
|
177
|
-
relation:
|
|
178
|
-
row.relationType === "MUTATED_VIA" ? ("write" as const) : ("read" as const),
|
|
179
|
-
name: row.name,
|
|
180
|
-
path: row.path,
|
|
181
|
-
method: row.method,
|
|
182
|
-
params: row.params ?? "[]",
|
|
183
|
-
body: row.body ?? "[]",
|
|
184
|
-
response: row.response ?? "[]",
|
|
185
|
-
metadata: row.metadata ?? "{}",
|
|
186
|
-
dependencies: row.dependencies.filter(
|
|
187
|
-
(dep): dep is EndpointDependency => dep.depPath != null,
|
|
188
|
-
),
|
|
189
|
-
rules: row.rules.filter((rule): rule is string => Boolean(rule)),
|
|
190
|
-
};
|
|
191
|
-
}),
|
|
192
|
-
);
|
|
225
|
+
const allEndpoints = dedupeEndpoints(endpointRows.map(toResolvedEndpoint));
|
|
193
226
|
|
|
194
227
|
const servicesRaw = await config.neo4j.query(
|
|
195
228
|
`UNWIND $names AS conceptName
|
|
196
|
-
MATCH (c
|
|
229
|
+
MATCH (c:${L.concept} {${P.name}: conceptName})-[:${R.specializes}*0..3]->(ancestor:${L.concept})
|
|
197
230
|
WITH conceptName, collect(DISTINCT ancestor) AS family
|
|
198
231
|
UNWIND family AS related
|
|
199
|
-
MATCH (related)-[
|
|
232
|
+
MATCH (related)-[:${R.requestedVia}]->(svc:${L.service})
|
|
200
233
|
WITH conceptName, related, svc
|
|
201
|
-
OPTIONAL MATCH (rService
|
|
202
|
-
OPTIONAL MATCH (rConcept
|
|
234
|
+
OPTIONAL MATCH (rService:${L.rule})-[:${R.governs}]->(svc)
|
|
235
|
+
OPTIONAL MATCH (rConcept:${L.rule})-[:${R.governs}]->(related)
|
|
203
236
|
RETURN conceptName AS concept,
|
|
204
|
-
svc.name AS serviceName,
|
|
205
|
-
svc.builtInId AS builtInId,
|
|
206
|
-
svc.description AS description,
|
|
207
|
-
svc.metadata AS metadata,
|
|
208
|
-
collect(DISTINCT rService.description) +
|
|
209
|
-
collect(DISTINCT rConcept.description) AS rules`,
|
|
237
|
+
svc.${P.name} AS serviceName,
|
|
238
|
+
svc.${P.builtInId} AS builtInId,
|
|
239
|
+
svc.${P.description} AS description,
|
|
240
|
+
svc.${P.metadata} AS metadata,
|
|
241
|
+
collect(DISTINCT rService.${P.description}) +
|
|
242
|
+
collect(DISTINCT rConcept.${P.description}) AS rules`,
|
|
210
243
|
{ names: conceptNames },
|
|
211
244
|
);
|
|
212
245
|
|
|
@@ -228,53 +261,34 @@ export async function resolveFromGraph(prompt: string, config: ResolverConfig) {
|
|
|
228
261
|
let servicingEndpoints: ResolvedEndpoint[] = [];
|
|
229
262
|
if (services.length > 0) {
|
|
230
263
|
const servicingRaw = await config.neo4j.query(
|
|
231
|
-
`MATCH (c
|
|
232
|
-
OPTIONAL MATCH (e)-[d
|
|
264
|
+
`MATCH (c:${L.concept} {${P.name}: '${SERVICE_REQUEST}'})-[rel:${R.queriedVia}|${R.mutatedVia}]->(e:${L.endpoint})
|
|
265
|
+
OPTIONAL MATCH (e)-[d:${R.dependsOn}]->(dep:${L.endpoint})
|
|
233
266
|
WITH c, rel, e,
|
|
234
267
|
collect(DISTINCT {
|
|
235
|
-
depPath: dep.path,
|
|
236
|
-
depMethod: dep.method,
|
|
237
|
-
paramName: d.paramName,
|
|
238
|
-
fromField: d.fromField
|
|
268
|
+
depPath: dep.${P.path},
|
|
269
|
+
depMethod: dep.${P.method},
|
|
270
|
+
paramName: d.${P.paramName},
|
|
271
|
+
fromField: d.${P.fromField}
|
|
239
272
|
}) AS dependencies
|
|
240
|
-
OPTIONAL MATCH (rEndpoint
|
|
241
|
-
OPTIONAL MATCH (rConcept
|
|
242
|
-
RETURN '
|
|
273
|
+
OPTIONAL MATCH (rEndpoint:${L.rule})-[:${R.governs}]->(e)
|
|
274
|
+
OPTIONAL MATCH (rConcept:${L.rule})-[:${R.governs}]->(c)
|
|
275
|
+
RETURN '${SERVICE_REQUEST}' AS concept,
|
|
243
276
|
type(rel) AS relationType,
|
|
244
|
-
e.name AS name,
|
|
245
|
-
e.path AS path,
|
|
246
|
-
e.method AS method,
|
|
247
|
-
e.params AS params,
|
|
248
|
-
e.body AS body,
|
|
249
|
-
e.response AS response,
|
|
250
|
-
e.metadata AS metadata,
|
|
277
|
+
e.${P.name} AS name,
|
|
278
|
+
e.${P.path} AS path,
|
|
279
|
+
e.${P.method} AS method,
|
|
280
|
+
e.${P.params} AS params,
|
|
281
|
+
e.${P.body} AS body,
|
|
282
|
+
e.${P.response} AS response,
|
|
283
|
+
e.${P.metadata} AS metadata,
|
|
251
284
|
dependencies,
|
|
252
|
-
collect(DISTINCT rEndpoint.description) +
|
|
253
|
-
collect(DISTINCT rConcept.description) AS rules`,
|
|
285
|
+
collect(DISTINCT rEndpoint.${P.description}) +
|
|
286
|
+
collect(DISTINCT rConcept.${P.description}) AS rules`,
|
|
254
287
|
{},
|
|
255
288
|
);
|
|
256
289
|
|
|
257
290
|
servicingEndpoints = dedupeEndpoints(
|
|
258
|
-
asArray<EndpointRow>(JSON.parse(servicingRaw)).map(
|
|
259
|
-
return {
|
|
260
|
-
concept: row.concept,
|
|
261
|
-
relation:
|
|
262
|
-
row.relationType === "MUTATED_VIA"
|
|
263
|
-
? ("write" as const)
|
|
264
|
-
: ("read" as const),
|
|
265
|
-
name: row.name,
|
|
266
|
-
path: row.path,
|
|
267
|
-
method: row.method,
|
|
268
|
-
params: row.params ?? "[]",
|
|
269
|
-
body: row.body ?? "[]",
|
|
270
|
-
response: row.response ?? "[]",
|
|
271
|
-
metadata: row.metadata ?? "{}",
|
|
272
|
-
dependencies: row.dependencies.filter(
|
|
273
|
-
(dep): dep is EndpointDependency => dep.depPath != null,
|
|
274
|
-
),
|
|
275
|
-
rules: row.rules.filter((rule): rule is string => Boolean(rule)),
|
|
276
|
-
};
|
|
277
|
-
}),
|
|
291
|
+
asArray<EndpointRow>(JSON.parse(servicingRaw)).map(toResolvedEndpoint),
|
|
278
292
|
);
|
|
279
293
|
}
|
|
280
294
|
|
|
@@ -291,14 +305,30 @@ export async function resolveFromGraph(prompt: string, config: ResolverConfig) {
|
|
|
291
305
|
}
|
|
292
306
|
}
|
|
293
307
|
|
|
294
|
-
// ---------------------------------------------------------------------------
|
|
295
|
-
// Internal helpers
|
|
296
|
-
// ---------------------------------------------------------------------------
|
|
297
|
-
|
|
298
308
|
function asArray<T>(value: unknown) {
|
|
299
309
|
return Array.isArray(value) ? (value as T[]) : ([] as T[]);
|
|
300
310
|
}
|
|
301
311
|
|
|
312
|
+
/** Maps a Cypher row to an endpoint. The string defaults stand in for columns
|
|
313
|
+
* Neo4j returns as null, which downstream JSON.parse calls would choke on. */
|
|
314
|
+
function toResolvedEndpoint(row: EndpointRow) {
|
|
315
|
+
return {
|
|
316
|
+
concept: row.concept,
|
|
317
|
+
relation: row.relationType === R.mutatedVia ? ("write" as const) : ("read" as const),
|
|
318
|
+
name: row.name,
|
|
319
|
+
path: row.path,
|
|
320
|
+
method: row.method,
|
|
321
|
+
params: row.params ?? "[]",
|
|
322
|
+
body: row.body ?? "[]",
|
|
323
|
+
response: row.response ?? "[]",
|
|
324
|
+
metadata: row.metadata ?? "{}",
|
|
325
|
+
dependencies: row.dependencies.filter(
|
|
326
|
+
(dep): dep is EndpointDependency => dep.depPath != null,
|
|
327
|
+
),
|
|
328
|
+
rules: row.rules.filter((rule): rule is string => Boolean(rule)),
|
|
329
|
+
} satisfies ResolvedEndpoint;
|
|
330
|
+
}
|
|
331
|
+
|
|
302
332
|
function dedupeEndpoints(endpoints: ResolvedEndpoint[]) {
|
|
303
333
|
const seen = new Set<string>();
|
|
304
334
|
const deduped: ResolvedEndpoint[] = [];
|
package/src/lib/index.ts
CHANGED
|
@@ -2,15 +2,21 @@
|
|
|
2
2
|
export type {
|
|
3
3
|
CortexConfig,
|
|
4
4
|
CortexAgentDefinition,
|
|
5
|
+
ControlCenterConfig,
|
|
5
6
|
KnowledgeConfig,
|
|
6
7
|
DatabaseConfig,
|
|
8
|
+
RedisConfig,
|
|
7
9
|
StorageConfig,
|
|
8
10
|
PromptContext,
|
|
9
11
|
ToolContext,
|
|
12
|
+
ToolSet,
|
|
10
13
|
ToolSetFactory,
|
|
11
14
|
} from "./config";
|
|
12
15
|
export { defineAgent } from "./config";
|
|
13
16
|
|
|
17
|
+
// Provider shape, so a consumer can name what it passes to the model helpers.
|
|
18
|
+
export type { ProviderConfig } from "./ai/helpers";
|
|
19
|
+
|
|
14
20
|
export type { ContextConfig, ThreadContextMeta } from "./ai/context/types";
|
|
15
21
|
|
|
16
22
|
// Types consumers may need
|
|
@@ -28,12 +34,13 @@ export type {
|
|
|
28
34
|
export { createRequestInterceptor } from "./ai/interceptors/request-interceptor";
|
|
29
35
|
|
|
30
36
|
// Tools (consumers may register custom tools or use built-in ones)
|
|
31
|
-
export { captureFilesTool } from "./ai/tools/capture-files.tool";
|
|
32
37
|
export { createQueryGraphTool } from "./ai/tools/query-graph.tool";
|
|
33
38
|
export { createExecuteCodeTool } from "./ai/tools/execute-code.tool";
|
|
34
39
|
|
|
35
|
-
// Graph (consumers may use independently)
|
|
40
|
+
// Graph (consumers may use independently). The contract itself lives in
|
|
41
|
+
// @cortex/contracts/graph — see ./graph/index — and is re-exported through here.
|
|
36
42
|
export * from "./graph/index";
|
|
37
43
|
|
|
38
|
-
//
|
|
39
|
-
|
|
44
|
+
// The wire contract, re-exported so consumers get it without a second import path.
|
|
45
|
+
// Its home is @cortex/contracts/wire, which the client SDKs compile in too.
|
|
46
|
+
export * from "@cortex/contracts/wire";
|
package/src/lib/redis.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Redis } from "ioredis";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The two long-lived connections everything Redis-backed shares. A subscriber
|
|
5
|
+
* connection cannot issue normal commands, so pub/sub listening gets its own;
|
|
6
|
+
* the publisher carries everything else (claims, stream appends, PUBLISH).
|
|
7
|
+
* Blocking stream reads never run on either — each reader duplicates its own
|
|
8
|
+
* connection, or one blocked XREAD would stall every claim and append behind it.
|
|
9
|
+
*/
|
|
10
|
+
export type RedisConnections = {
|
|
11
|
+
publisher: Redis;
|
|
12
|
+
subscriber: Redis;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Without an `error` listener ioredis raises unhandled-error events, which can
|
|
17
|
+
* crash the process — with one, a flapping or unreachable Redis becomes a log
|
|
18
|
+
* line while ioredis reconnects underneath.
|
|
19
|
+
*/
|
|
20
|
+
export function withRedisLogging(client: Redis, role: string) {
|
|
21
|
+
client.on("error", (error: unknown) => console.error(`[cortex-server] redis ${role}:`, error));
|
|
22
|
+
return client;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Cached per URL on `globalThis` so hot reloads and repeated `createCortex`
|
|
27
|
+
* calls reuse the connections instead of opening new ones each time.
|
|
28
|
+
*/
|
|
29
|
+
const store = globalThis as typeof globalThis & {
|
|
30
|
+
__cortexRedis?: Map<string, RedisConnections>;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export function getRedisConnections(url: string) {
|
|
34
|
+
store.__cortexRedis ??= new Map();
|
|
35
|
+
let connections = store.__cortexRedis.get(url);
|
|
36
|
+
if (!connections) {
|
|
37
|
+
connections = {
|
|
38
|
+
publisher: withRedisLogging(new Redis(url), "publisher"),
|
|
39
|
+
subscriber: withRedisLogging(new Redis(url), "subscriber"),
|
|
40
|
+
};
|
|
41
|
+
store.__cortexRedis.set(url, connections);
|
|
42
|
+
}
|
|
43
|
+
return connections;
|
|
44
|
+
}
|
package/src/lib/routes/chat.ts
CHANGED
|
@@ -1,85 +1,114 @@
|
|
|
1
|
+
import { EventType, chatParamsFromRequest, resumeServerSentEventsResponse } from "@tanstack/ai";
|
|
2
|
+
import type { AbortRunResult } from "@cortex/contracts/wire";
|
|
1
3
|
import { Hono } from "hono";
|
|
2
|
-
import {
|
|
3
|
-
import z from "zod";
|
|
4
|
+
import { bodyLimit } from "hono/body-limit";
|
|
4
5
|
import { HTTPException } from "hono/http-exception";
|
|
5
|
-
import type { CortexAppEnv } from "
|
|
6
|
-
import { requireAuth } from "
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { notify } from "
|
|
10
|
-
import {
|
|
6
|
+
import type { CortexAppEnv } from "@/types";
|
|
7
|
+
import { requireAuth } from "@/auth/middleware";
|
|
8
|
+
import { startTurn } from "@/ai/index";
|
|
9
|
+
import { abortRun, getRunId, joinLog, offsetBelongsToRun } from "@/ai/active-runs";
|
|
10
|
+
import { notify } from "@/ws/connections";
|
|
11
|
+
import { requireOwnedThread } from "./owned-thread";
|
|
12
|
+
import { toThreadSummary } from "@/types";
|
|
13
|
+
|
|
14
|
+
const CHAT_BODY_MAX_BYTES = 1024 * 1024;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The answer to "attach me to the run on this thread" when there is no longer
|
|
18
|
+
* one. An empty body would be the obvious reply, but the client reads every
|
|
19
|
+
* attach as a stream and treats a missing one as a transport failure — so the
|
|
20
|
+
* run is reported over, which is what actually happened, and the client settles
|
|
21
|
+
* the turn from the database like any other ending.
|
|
22
|
+
*/
|
|
23
|
+
function runEnded() {
|
|
24
|
+
const finished = { type: EventType.RUN_FINISHED, timestamp: Date.now() };
|
|
25
|
+
|
|
26
|
+
return new Response(`data: ${JSON.stringify(finished)}\n\n`, {
|
|
27
|
+
headers: {
|
|
28
|
+
"Content-Type": "text/event-stream",
|
|
29
|
+
"Cache-Control": "no-cache",
|
|
30
|
+
Connection: "keep-alive",
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
}
|
|
11
34
|
|
|
12
35
|
export function createChatRoutes() {
|
|
13
36
|
const app = new Hono<CortexAppEnv>();
|
|
14
37
|
|
|
15
|
-
app.post(
|
|
16
|
-
"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
app.post("/chat", requireAuth, bodyLimit({ maxSize: CHAT_BODY_MAX_BYTES }), async function (c) {
|
|
39
|
+
const config = c.get("agentConfig");
|
|
40
|
+
const { id: userId, token } = c.get("user");
|
|
41
|
+
|
|
42
|
+
let params: Awaited<ReturnType<typeof chatParamsFromRequest>>;
|
|
43
|
+
try {
|
|
44
|
+
params = await chatParamsFromRequest(c.req.raw);
|
|
45
|
+
} catch (thrown) {
|
|
46
|
+
// The AG-UI validator rejects a malformed body by throwing the
|
|
47
|
+
// 400 it wants sent; Hono has no such convention, so return it.
|
|
48
|
+
if (thrown instanceof Response) return thrown;
|
|
49
|
+
throw thrown;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const thread = await requireOwnedThread(c, params.threadId);
|
|
53
|
+
|
|
54
|
+
// A dropped connection re-POSTs the same body with Last-Event-ID.
|
|
55
|
+
// The run is already producing into its log, so this replays from
|
|
56
|
+
// where the client left off rather than starting a second turn. A
|
|
57
|
+
// run that has since finished sends the client back to the messages
|
|
58
|
+
// endpoint, which by then holds everything the log would have.
|
|
59
|
+
const resumeOffset = c.req.header("Last-Event-ID");
|
|
60
|
+
if (resumeOffset) {
|
|
61
|
+
const runId = await getRunId(thread.id);
|
|
62
|
+
if (!runId) return runEnded();
|
|
63
|
+
if (!offsetBelongsToRun(resumeOffset, runId)) {
|
|
64
|
+
throw new HTTPException(400, { message: "Invalid resume offset" });
|
|
38
65
|
}
|
|
39
66
|
|
|
40
|
-
return
|
|
41
|
-
|
|
42
|
-
|
|
67
|
+
return resumeServerSentEventsResponse({
|
|
68
|
+
adapter: joinLog(thread.id, runId, resumeOffset),
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const requestContext = config.resolveRequestContext
|
|
73
|
+
? await config.resolveRequestContext(c.req.raw)
|
|
74
|
+
: {};
|
|
75
|
+
|
|
76
|
+
// Null means a stop beat the run to its own announcement; the run is
|
|
77
|
+
// over, which is what actually happened.
|
|
78
|
+
return (
|
|
79
|
+
(await startTurn(params, thread, userId, token, requestContext, config)) ?? runEnded()
|
|
80
|
+
);
|
|
81
|
+
});
|
|
43
82
|
|
|
83
|
+
/** Attaches a reload, a thread switch, or a second tab to the thread's live run. */
|
|
44
84
|
app.get("/chat/:chatId/stream", requireAuth, async function (c) {
|
|
45
|
-
const config = c.get("agentConfig");
|
|
46
|
-
const agentId = c.get("agentId");
|
|
47
85
|
const chatId = c.req.param("chatId");
|
|
48
|
-
|
|
49
|
-
if (!thread || thread.agentId !== agentId) {
|
|
50
|
-
throw new HTTPException(404, { message: "Not found" });
|
|
51
|
-
}
|
|
86
|
+
await requireOwnedThread(c, chatId);
|
|
52
87
|
|
|
53
|
-
const
|
|
54
|
-
if (!
|
|
55
|
-
return c.body(null, 204);
|
|
56
|
-
}
|
|
88
|
+
const runId = await getRunId(chatId);
|
|
89
|
+
if (!runId) return runEnded();
|
|
57
90
|
|
|
58
|
-
return
|
|
59
|
-
headers: {
|
|
60
|
-
"Content-Type": "text/event-stream",
|
|
61
|
-
"Cache-Control": "no-cache",
|
|
62
|
-
Connection: "keep-alive",
|
|
63
|
-
},
|
|
64
|
-
});
|
|
91
|
+
return resumeServerSentEventsResponse({ adapter: joinLog(chatId, runId) });
|
|
65
92
|
});
|
|
66
93
|
|
|
67
94
|
app.post("/chat/:chatId/abort", requireAuth, async function (c) {
|
|
68
|
-
const config = c.get("agentConfig");
|
|
69
95
|
const agentId = c.get("agentId");
|
|
70
96
|
const userId = c.get("user").id;
|
|
71
97
|
const chatId = c.req.param("chatId");
|
|
72
|
-
const thread = await
|
|
73
|
-
if (!thread || thread.agentId !== agentId) {
|
|
74
|
-
throw new HTTPException(404, { message: "Not found" });
|
|
75
|
-
}
|
|
98
|
+
const thread = await requireOwnedThread(c, chatId);
|
|
76
99
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
100
|
+
// Only announce an ending that happened: the client's stop button can
|
|
101
|
+
// outlive the server run (it drains the durability log after the
|
|
102
|
+
// producer commits), and a run-finished for a run that already ended
|
|
103
|
+
// can land before its own run-started and pin the thread as running.
|
|
104
|
+
const aborted = await abortRun(chatId);
|
|
105
|
+
if (aborted) {
|
|
106
|
+
notify(userId, agentId, {
|
|
107
|
+
type: "thread:run-finished",
|
|
108
|
+
payload: { thread: toThreadSummary(thread, false) },
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
return c.json({ aborted } satisfies AbortRunResult);
|
|
83
112
|
});
|
|
84
113
|
|
|
85
114
|
return app;
|