divi 0.0.1.dev23__tar.gz → 0.0.1.dev28__tar.gz

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 (230) hide show
  1. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/PKG-INFO +1 -1
  2. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/graphql/package.json +2 -2
  3. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/package.json +9 -8
  4. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/__init__.py +4 -2
  5. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/decorators/obs_openai.py +20 -5
  6. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/decorators/observable.py +8 -3
  7. divi-0.0.1.dev28/divi/evaluation/__init__.py +4 -0
  8. divi-0.0.1.dev28/divi/evaluation/evaluate.py +57 -0
  9. divi-0.0.1.dev28/divi/evaluation/evaluator.py +161 -0
  10. divi-0.0.1.dev28/divi/evaluation/prompts.py +14 -0
  11. divi-0.0.1.dev28/divi/evaluation/scores.py +8 -0
  12. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/services/init.py +2 -1
  13. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/session/setup.py +5 -2
  14. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/package.json +1 -1
  15. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/pnpm-lock.yaml +868 -780
  16. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/turbo.json +2 -1
  17. divi-0.0.1.dev23/divi/config/config.py +0 -0
  18. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/.air.toml +0 -0
  19. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/.dockerignore +0 -0
  20. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/.github/dependabot.yml +0 -0
  21. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/.gitignore +0 -0
  22. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/LICENSE +0 -0
  23. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/README.md +0 -0
  24. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/README.md +0 -0
  25. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/docs/README.md +0 -0
  26. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/docs/concepts/session.mdx +0 -0
  27. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/docs/development/roadmap.mdx +0 -0
  28. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/docs/docs.json +0 -0
  29. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/docs/favicon.ico +0 -0
  30. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/docs/images/researcher-angel.png +0 -0
  31. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/docs/images/scholar-angel.png +0 -0
  32. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/docs/introduction.mdx +0 -0
  33. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/docs/package.json +0 -0
  34. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/docs/quickstart/trace.mdx +0 -0
  35. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/docs/snippets/snippet-intro.mdx +0 -0
  36. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/docs/tutorials/openai.mdx +0 -0
  37. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/graphql/Dockerfile +0 -0
  38. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/graphql/README.md +0 -0
  39. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/graphql/codegen.ts +0 -0
  40. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/graphql/src/datasources/auth-api.ts +0 -0
  41. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/graphql/src/datasources/datapark-api.ts +0 -0
  42. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/graphql/src/index.ts +0 -0
  43. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/graphql/src/resolvers.ts +0 -0
  44. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/graphql/src/schema.graphql +0 -0
  45. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/graphql/src/types/context.d.ts +0 -0
  46. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/graphql/src/types/response.d.ts +0 -0
  47. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/graphql/src/types/types.d.ts +0 -0
  48. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/graphql/tsconfig.json +0 -0
  49. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/.gitignore +0 -0
  50. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/README.md +0 -0
  51. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/@modal/(.)traces/[id]/page.tsx +0 -0
  52. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/@modal/default.tsx +0 -0
  53. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/api-keys/actions.ts +0 -0
  54. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/api-keys/components/columns.tsx +0 -0
  55. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/api-keys/components/create-dialog.tsx +0 -0
  56. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/api-keys/components/data-table-cell-viewer.tsx +0 -0
  57. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/api-keys/components/data-table-toolbar.tsx +0 -0
  58. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/api-keys/components/data-table.tsx +0 -0
  59. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/api-keys/components/delete-dialog.tsx +0 -0
  60. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/api-keys/data/data.tsx +0 -0
  61. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/api-keys/data/schema.ts +0 -0
  62. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/api-keys/layout.tsx +0 -0
  63. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/api-keys/page.tsx +0 -0
  64. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/components/app-sidebar.tsx +0 -0
  65. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/components/nav-main.tsx +0 -0
  66. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/components/nav-secondary.tsx +0 -0
  67. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/components/nav-user.tsx +0 -0
  68. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/components/site-header.tsx +0 -0
  69. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/layout.tsx +0 -0
  70. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/settings/account/components/account-form.tsx +0 -0
  71. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/settings/account/page.tsx +0 -0
  72. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/settings/appearance/components/appearance-form.tsx +0 -0
  73. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/settings/appearance/page.tsx +0 -0
  74. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/settings/components/profile-form.tsx +0 -0
  75. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/settings/components/sidebar-nav.tsx +0 -0
  76. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/settings/layout.tsx +0 -0
  77. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/settings/page.tsx +0 -0
  78. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/traces/(children)/[id]/components/Span.tsx +0 -0
  79. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/traces/(children)/[id]/components/responsive-resizable.tsx +0 -0
  80. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/traces/(children)/[id]/components/trace-board.tsx +0 -0
  81. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/traces/(children)/[id]/components/trace-chart.tsx +0 -0
  82. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/traces/(children)/[id]/page.tsx +0 -0
  83. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/traces/(overview)/components/columns.tsx +0 -0
  84. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/traces/(overview)/components/data-table-row-action.tsx +0 -0
  85. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/traces/(overview)/components/data-table-toolbar.tsx +0 -0
  86. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/traces/(overview)/components/data-table.tsx +0 -0
  87. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/traces/(overview)/data/data.tsx +0 -0
  88. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/traces/(overview)/data/schema.ts +0 -0
  89. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/traces/(overview)/layout.tsx +0 -0
  90. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/traces/(overview)/page.tsx +0 -0
  91. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/usages/actions.ts +0 -0
  92. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/usages/components/usage-board.tsx +0 -0
  93. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/usages/components/usage-chart.tsx +0 -0
  94. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/usages/layout.tsx +0 -0
  95. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/dashboard/usages/page.tsx +0 -0
  96. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/favicon.ico +0 -0
  97. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/home/components/home-header.tsx +0 -0
  98. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/home/components/home-hero.tsx +0 -0
  99. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/home/page.tsx +0 -0
  100. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/layout.tsx +0 -0
  101. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/login/components/login-form.tsx +0 -0
  102. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/login/page.tsx +0 -0
  103. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/page.tsx +0 -0
  104. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/signup/components/signup-form.tsx +0 -0
  105. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/app/signup/page.tsx +0 -0
  106. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/components/ApolloWrapper.tsx +0 -0
  107. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/components/Highter.tsx +0 -0
  108. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/components/Modal.tsx +0 -0
  109. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/components/calendar.tsx +0 -0
  110. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/components/data-table-column-header.tsx +0 -0
  111. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/components/data-table-faceted-filter.tsx +0 -0
  112. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/components/data-table-pagination.tsx +0 -0
  113. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/components/data-table-row.tsx +0 -0
  114. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/components/data-table-view-options.tsx +0 -0
  115. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/components/date-picker.tsx +0 -0
  116. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/components/mode-switcher.tsx +0 -0
  117. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/components/theme-provider.tsx +0 -0
  118. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/components.json +0 -0
  119. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/hooks/actionState.ts +0 -0
  120. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/hooks/apolloClient.ts +0 -0
  121. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/lib/callback/toast-callback.ts +0 -0
  122. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/lib/callback/with-callback.ts +0 -0
  123. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/lib/server/README.md +0 -0
  124. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/lib/server/auth.ts +0 -0
  125. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/lib/server/cookies.ts +0 -0
  126. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/lib/server/openai.ts +0 -0
  127. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/lib/server/span.ts +0 -0
  128. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/lib/types/span.d.ts +0 -0
  129. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/lib/types/state.d.ts +0 -0
  130. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/lib/types/usage.d.ts +0 -0
  131. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/lib/utils.ts +0 -0
  132. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/middleware.ts +0 -0
  133. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/next-env.d.ts +0 -0
  134. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/next.config.ts +0 -0
  135. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/postcss.config.mjs +0 -0
  136. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/public/peeking-angel.png +0 -0
  137. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/public/thinking-angel.png +0 -0
  138. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/tsconfig.json +0 -0
  139. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/apps/web/vercel.json +0 -0
  140. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/biome.json +0 -0
  141. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/compose-dev.yml +0 -0
  142. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/decorators/__init__.py +0 -0
  143. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/proto/common/v1/common.proto +0 -0
  144. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/proto/common/v1/common_pb2.py +0 -0
  145. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/proto/common/v1/common_pb2.pyi +0 -0
  146. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/proto/core/health/v1/health_service.proto +0 -0
  147. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/proto/core/health/v1/health_service_pb2.py +0 -0
  148. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/proto/core/health/v1/health_service_pb2.pyi +0 -0
  149. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/proto/core/health/v1/health_service_pb2_grpc.py +0 -0
  150. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/proto/metric/v1/metric.proto +0 -0
  151. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/proto/metric/v1/metric_pb2.py +0 -0
  152. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/proto/metric/v1/metric_pb2.pyi +0 -0
  153. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/proto/trace/v1/trace.proto +0 -0
  154. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/proto/trace/v1/trace_pb2.py +0 -0
  155. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/proto/trace/v1/trace_pb2.pyi +0 -0
  156. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/services/__init__.py +0 -0
  157. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/services/auth/__init__.py +0 -0
  158. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/services/auth/auth.py +0 -0
  159. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/services/auth/init.py +0 -0
  160. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/services/auth/tokman.py +0 -0
  161. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/services/core/__init__.py +0 -0
  162. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/services/core/core.py +0 -0
  163. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/services/core/finish.py +0 -0
  164. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/services/core/init.py +0 -0
  165. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/services/datapark/__init__.py +0 -0
  166. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/services/datapark/datapark.py +0 -0
  167. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/services/datapark/init.py +0 -0
  168. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/services/finish.py +0 -0
  169. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/services/service.py +0 -0
  170. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/session/__init__.py +0 -0
  171. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/session/session.py +0 -0
  172. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/session/teardown.py +0 -0
  173. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/signals/__init__.py +0 -0
  174. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/signals/trace/__init__.py +0 -0
  175. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/signals/trace/trace.py +0 -0
  176. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/divi/utils.py +0 -0
  177. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/docker-compose.yml +0 -0
  178. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/docs/README.md +0 -0
  179. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/docs/developer_tools.md +0 -0
  180. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/docs/images/architecture.svg +0 -0
  181. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/docs/images/favicon.ico +0 -0
  182. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/docs/images/og-image.png +0 -0
  183. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/docs/images/storage.svg +0 -0
  184. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/docs/package_readme.md +0 -0
  185. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/go.work +0 -0
  186. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/go.work.sum +0 -0
  187. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/hatch.toml +0 -0
  188. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/packages/README.md +0 -0
  189. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/pnpm-workspace.yaml +0 -0
  190. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/pyproject.toml +0 -0
  191. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/scripts/README.md +0 -0
  192. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/scripts/hatch_build.py +0 -0
  193. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/scripts/key_build.py +0 -0
  194. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/scripts/proto_build.py +0 -0
  195. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/README.md +0 -0
  196. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/go.mod +0 -0
  197. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/go.sum +0 -0
  198. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/app/auth/handler/api.go +0 -0
  199. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/app/auth/handler/api_key.go +0 -0
  200. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/app/auth/handler/auth.go +0 -0
  201. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/app/auth/handler/user.go +0 -0
  202. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/app/auth/router/router.go +0 -0
  203. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/app/core/.keep +0 -0
  204. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/app/datapark/handler/api.go +0 -0
  205. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/app/datapark/handler/metric.go +0 -0
  206. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/app/datapark/handler/openai.go +0 -0
  207. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/app/datapark/handler/session.go +0 -0
  208. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/app/datapark/handler/trace.go +0 -0
  209. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/app/datapark/handler/usage.go +0 -0
  210. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/app/datapark/router/router.go +0 -0
  211. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/pkg/auth/auth.go +0 -0
  212. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/pkg/auth/middleware.go +0 -0
  213. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/pkg/config/config.go +0 -0
  214. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/pkg/database/connect.go +0 -0
  215. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/pkg/database/database.go +0 -0
  216. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/pkg/model/api_key.go +0 -0
  217. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/pkg/model/openai.go +0 -0
  218. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/pkg/model/session.go +0 -0
  219. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/pkg/model/trace.go +0 -0
  220. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/pkg/model/usage.go +0 -0
  221. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/internal/pkg/model/user.go +0 -0
  222. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/pb/common.pb.go +0 -0
  223. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/pb/health_service.pb.go +0 -0
  224. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/pb/health_service_grpc.pb.go +0 -0
  225. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/pb/metric.pb.go +0 -0
  226. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/services/pb/trace.pb.go +0 -0
  227. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/tests/__init__.py +0 -0
  228. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/tests/unit_tests/decorators/test_obs_openai.py +0 -0
  229. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/tests/unit_tests/decorators/test_observable.py +0 -0
  230. {divi-0.0.1.dev23 → divi-0.0.1.dev28}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: divi
3
- Version: 0.0.1.dev23
3
+ Version: 0.0.1.dev28
4
4
  Summary: The Agent Platform for Observability & Evaluation
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.11
@@ -13,7 +13,7 @@
13
13
  "@apollo/datasource-rest": "^6.4.1",
14
14
  "@apollo/server": "^4.12.0",
15
15
  "@apollo/utils.keyvaluecache": "^3.1.0",
16
- "graphql": "^16.10.0",
16
+ "graphql": "^16.11.0",
17
17
  "graphql-tag": "^2.12.6"
18
18
  },
19
19
  "devDependencies": {
@@ -21,7 +21,7 @@
21
21
  "@graphql-codegen/typescript": "^4.1.6",
22
22
  "@graphql-codegen/typescript-resolvers": "^4.5.0",
23
23
  "@workspace/typescript-config": "workspace:*",
24
- "nodemon": "^3.1.9",
24
+ "nodemon": "^3.1.10",
25
25
  "ts-node-dev": "^2.0.0",
26
26
  "typescript": "catalog:"
27
27
  }
@@ -2,6 +2,7 @@
2
2
  "name": "@app/web",
3
3
  "private": true,
4
4
  "type": "module",
5
+ "packageManager": "pnpm@10.6.5",
5
6
  "scripts": {
6
7
  "dev": "next dev --turbopack --port 4001",
7
8
  "build": "next build",
@@ -9,18 +10,19 @@
9
10
  "analyze": "ANALYZE=true pnpm build"
10
11
  },
11
12
  "dependencies": {
12
- "@apollo/client": "^3.13.7",
13
+ "@apollo/client": "^3.13.8",
13
14
  "@apollo/experimental-nextjs-app-support": "^0.11.11",
14
15
  "@dnd-kit/core": "^6.3.1",
15
16
  "@dnd-kit/modifiers": "^9.0.0",
16
17
  "@dnd-kit/sortable": "^10.0.0",
17
18
  "@dnd-kit/utilities": "^3.2.2",
18
19
  "@hookform/resolvers": "^4.1.3",
19
- "@icons-pack/react-simple-icons": "^12.6.0",
20
+ "@icons-pack/react-simple-icons": "^12.7.0",
20
21
  "@tabler/icons-react": "^3.31.0",
21
- "@tanstack/react-table": "^8.21.2",
22
+ "@tanstack/react-table": "^8.21.3",
22
23
  "@workspace/graphql-client": "workspace:*",
23
24
  "@workspace/ui": "workspace:*",
25
+ "date-fns": "catalog:",
24
26
  "highlight.js": "^11.11.1",
25
27
  "lucide-react": "catalog:",
26
28
  "next": "catalog:",
@@ -28,12 +30,11 @@
28
30
  "react": "catalog:",
29
31
  "react-day-picker": "catalog:",
30
32
  "react-dom": "catalog:",
31
- "react-hook-form": "^7.55.0",
32
- "recharts": "^2.15.2",
33
+ "react-hook-form": "^7.56.1",
34
+ "recharts": "^2.15.3",
33
35
  "server-only": "^0.0.1",
34
36
  "sonner": "catalog:",
35
- "zod": "^3.24.2",
36
- "date-fns": "catalog:"
37
+ "zod": "^3.24.3"
37
38
  },
38
39
  "devDependencies": {
39
40
  "@types/highlightjs": "^9.12.6",
@@ -41,7 +42,7 @@
41
42
  "@types/react": "catalog:",
42
43
  "@types/react-dom": "catalog:",
43
44
  "@workspace/typescript-config": "workspace:*",
44
- "openai": "^4.93.0",
45
+ "openai": "^4.96.0",
45
46
  "typescript": "catalog:"
46
47
  }
47
48
  }
@@ -2,6 +2,7 @@ from typing import Optional
2
2
 
3
3
  from . import proto
4
4
  from .decorators import obs_openai, observable
5
+ from .evaluation import Evaluator, Score
5
6
  from .services import Auth, Core, DataPark
6
7
  from .session import Session
7
8
 
@@ -11,6 +12,7 @@ _session: Optional[Session] = None
11
12
  _core: Optional[Core] = None
12
13
  _auth: Optional[Auth] = None
13
14
  _datapark: Optional[DataPark] = None
15
+ _evaluator: Optional[Evaluator] = None
14
16
 
15
- __version__ = "0.0.1.dev23"
16
- __all__ = ["proto", "obs_openai", "observable"]
17
+ __version__ = "0.0.1.dev28"
18
+ __all__ = ["proto", "obs_openai", "observable", "Score"]
@@ -2,7 +2,10 @@ import functools
2
2
  from collections.abc import Callable
3
3
  from typing import TYPE_CHECKING, TypeVar, Union
4
4
 
5
+ from typing_extensions import Optional
6
+
5
7
  from divi.decorators.observable import observable
8
+ from divi.evaluation.scores import Score
6
9
  from divi.utils import is_async
7
10
 
8
11
  if TYPE_CHECKING:
@@ -11,22 +14,34 @@ if TYPE_CHECKING:
11
14
  C = TypeVar("C", bound=Union["OpenAI", "AsyncOpenAI"])
12
15
 
13
16
 
14
- def _get_observable_create(create: Callable) -> Callable:
17
+ def _get_observable_create(
18
+ create: Callable,
19
+ name: Optional[str] = None,
20
+ scores: Optional[list[Score]] = None,
21
+ ) -> Callable:
15
22
  @functools.wraps(create)
16
23
  def observable_create(*args, stream: bool = False, **kwargs):
17
- decorator = observable(kind="llm")
24
+ decorator = observable(kind="llm", name=name, scores=scores)
18
25
  return decorator(create)(*args, stream=stream, **kwargs)
19
26
 
20
27
  # TODO Async Observable Create
21
28
  return observable_create if not is_async(create) else create
22
29
 
23
30
 
24
- def obs_openai(client: C) -> C:
31
+ def obs_openai(
32
+ client: C,
33
+ name: Optional[str] = "Chat Bot",
34
+ scores: Optional[list[Score]] = None,
35
+ ) -> C:
25
36
  """Make OpenAI client observable."""
26
37
  client.chat.completions.create = _get_observable_create(
27
- client.chat.completions.create
38
+ client.chat.completions.create,
39
+ name=name,
40
+ scores=scores,
28
41
  )
29
42
  client.completions.create = _get_observable_create(
30
- client.completions.create
43
+ client.completions.create,
44
+ name=name,
45
+ scores=scores,
31
46
  )
32
47
  return client
@@ -1,11 +1,9 @@
1
1
  import contextvars
2
2
  import functools
3
- import inspect
4
3
  from typing import (
5
4
  Any,
6
5
  Callable,
7
6
  Generic,
8
- List,
9
7
  Mapping,
10
8
  Optional,
11
9
  ParamSpec,
@@ -19,6 +17,8 @@ from typing import (
19
17
  from openai.types.chat import ChatCompletion
20
18
 
21
19
  import divi
20
+ from divi.evaluation.evaluate import evaluate_scores
21
+ from divi.evaluation.scores import Score
22
22
  from divi.proto.trace.v1.trace_pb2 import ScopeSpans
23
23
  from divi.session import SessionExtra
24
24
  from divi.session.setup import setup
@@ -54,6 +54,7 @@ def observable(
54
54
  kind: str = "function",
55
55
  *,
56
56
  name: Optional[str] = None,
57
+ scores: Optional[list[Score]] = None,
57
58
  metadata: Optional[Mapping[str, Any]] = None,
58
59
  ) -> Callable[[Callable[P, R]], WithSessionExtra[P, R]]: ...
59
60
 
@@ -66,6 +67,7 @@ def observable(
66
67
  kind = kwargs.pop("kind", "function")
67
68
  name = kwargs.pop("name", None)
68
69
  metadata = kwargs.pop("metadata", None)
70
+ scores: list[Score] = kwargs.pop("scores", None)
69
71
 
70
72
  def decorator(func):
71
73
  @functools.wraps(func)
@@ -88,7 +90,7 @@ def observable(
88
90
  # get the trace to collect data
89
91
  trace = session_extra.get("trace")
90
92
  if not trace:
91
- raise ValueError("Trace not found in session_extra")
93
+ raise ValueError("Trace not found in session context.")
92
94
  # TODO: collect inputs and outputs for SPAN_KIND_FUNCTION
93
95
  inputs = extract_flattened_inputs(func, *args, **kwargs)
94
96
  # create the span if it is the root span
@@ -107,6 +109,9 @@ def observable(
107
109
  inputs=inputs,
108
110
  completion=result,
109
111
  )
112
+ # evaluate the scores if they are provided
113
+ if scores is not None and scores.__len__() > 0:
114
+ evaluate_scores(inputs, outputs=result, scores=scores)
110
115
 
111
116
  return result
112
117
 
@@ -0,0 +1,4 @@
1
+ from .evaluator import Evaluator
2
+ from .scores import Score
3
+
4
+ __all__ = ["Evaluator", "Score"]
@@ -0,0 +1,57 @@
1
+ import copy
2
+ import os
3
+ from typing import Any, Dict, Optional
4
+
5
+ from openai.types.chat import ChatCompletion
6
+ from typing_extensions import List
7
+
8
+ import divi
9
+ from divi.evaluation import Evaluator
10
+ from divi.evaluation.evaluator import EvaluatorConfig
11
+ from divi.evaluation.scores import Score
12
+
13
+ OPENAI_API_KEY = "OPENAI_API_KEY"
14
+ OPENAI_BASE_URL = "OPENAI_BASE_URL"
15
+
16
+
17
+ def init_evaluator(config: Optional[EvaluatorConfig] = None):
18
+ _config = config or EvaluatorConfig()
19
+ api_key = _config.api_key if _config.api_key else os.getenv(OPENAI_API_KEY)
20
+ base_url = (
21
+ _config.base_url if _config.base_url else os.getenv(OPENAI_BASE_URL)
22
+ )
23
+ if api_key is None:
24
+ raise ValueError("API key is required for evaluator")
25
+ _config.api_key = api_key
26
+ _config.base_url = base_url
27
+ evaluator = Evaluator(_config)
28
+ return evaluator
29
+
30
+
31
+ def evaluate_scores(
32
+ inputs: Dict[str, Any],
33
+ outputs: ChatCompletion,
34
+ scores: List[Score],
35
+ config: Optional[EvaluatorConfig] = None,
36
+ ):
37
+ if not divi._evaluator:
38
+ divi._evaluator = init_evaluator(config)
39
+
40
+ # create conversation with result and inputs
41
+ input_messages = inputs.get("messages", None)
42
+ if input_messages is None:
43
+ raise ValueError("No messages found in inputs")
44
+ output_message = outputs.choices[0].message
45
+ if output_message is None:
46
+ raise ValueError("No message found in outputs")
47
+
48
+ conversations = copy.deepcopy(input_messages)
49
+ conversations.append(
50
+ {"role": output_message.role, "content": output_message.content}
51
+ )
52
+ evaluation_scores = divi._evaluator.evaluate(
53
+ "\n".join(f"{m['role']}: {m['content']}" for m in conversations), scores
54
+ )
55
+
56
+ # TODO: collect all evaluation scores and link them to span
57
+ print(evaluation_scores)
@@ -0,0 +1,161 @@
1
+ import asyncio
2
+ import concurrent.futures
3
+ import random
4
+ from typing import List, Literal, Optional
5
+
6
+ import openai
7
+ from pydantic import BaseModel
8
+
9
+ from divi.evaluation.prompts import PRESET_PROMPT, PROMPT_TEMPLATE
10
+ from divi.evaluation.scores import Score
11
+
12
+
13
+ class EvaluatorConfig:
14
+ def __init__(
15
+ self,
16
+ model: str = "gpt-4.1-nano",
17
+ temperature: float = 0.5,
18
+ max_concurrency: int = 10,
19
+ api_key: Optional[str] = None,
20
+ base_url: Optional[str] = None,
21
+ ):
22
+ self.model = model
23
+ self.api_key = api_key
24
+ self.base_url = base_url
25
+ self.temperature = temperature
26
+ self.max_concurrency = max_concurrency
27
+
28
+
29
+ class EvaluationResult(BaseModel):
30
+ name: Score
31
+ judgment: bool
32
+ reasoning: str
33
+
34
+
35
+ class EvaluationScore(BaseModel):
36
+ name: Score
37
+ score: float
38
+ representative_reasoning: str
39
+ all_evaluations: List[EvaluationResult]
40
+
41
+
42
+ class Evaluator:
43
+ def __init__(self, config: Optional[EvaluatorConfig] = None):
44
+ self.config = config or EvaluatorConfig()
45
+ self.async_client = openai.AsyncOpenAI(
46
+ api_key=self.config.api_key, base_url=self.config.base_url
47
+ )
48
+ self.sync_client = openai.OpenAI(
49
+ api_key=self.config.api_key, base_url=self.config.base_url
50
+ )
51
+
52
+ @staticmethod
53
+ def generate_prompt(conversation: str, score: Score) -> str:
54
+ return PROMPT_TEMPLATE.format(
55
+ requirements=PRESET_PROMPT[score.value], conversation=conversation
56
+ )
57
+
58
+ def _sync_evaluate_once(
59
+ self, conversation: str, score: Score
60
+ ) -> Optional[EvaluationResult]:
61
+ prompt = self.generate_prompt(conversation, score)
62
+ response = self.sync_client.beta.chat.completions.parse(
63
+ model=self.config.model,
64
+ messages=[{"role": "user", "content": prompt}],
65
+ temperature=self.config.temperature,
66
+ response_format=EvaluationResult,
67
+ )
68
+ return response.choices[0].message.parsed
69
+
70
+ async def _async_evaluate_once(
71
+ self, conversation: str, score: Score
72
+ ) -> Optional[EvaluationResult]:
73
+ prompt = self.generate_prompt(conversation, score)
74
+ response = await self.async_client.beta.chat.completions.parse(
75
+ model=self.config.model,
76
+ messages=[{"role": "user", "content": prompt}],
77
+ temperature=self.config.temperature,
78
+ response_format=EvaluationResult,
79
+ )
80
+ return response.choices[0].message.parsed
81
+
82
+ def _aggregate_result(
83
+ self, name: Score, evaluations: List[EvaluationResult]
84
+ ) -> EvaluationScore:
85
+ n = len(evaluations)
86
+ true_count = sum(1 for e in evaluations if e.judgment is True)
87
+ score = true_count / n
88
+ majority_judgment = True if true_count >= (n / 2) else False
89
+ majority_reasons = [
90
+ e.reasoning for e in evaluations if e.judgment == majority_judgment
91
+ ]
92
+ representative_reasoning = (
93
+ random.choice(majority_reasons) if majority_reasons else ""
94
+ )
95
+ return EvaluationScore(
96
+ name=name,
97
+ score=score,
98
+ representative_reasoning=representative_reasoning,
99
+ all_evaluations=evaluations,
100
+ )
101
+
102
+ def _aggregate_results(
103
+ self, evaluations: List[EvaluationResult]
104
+ ) -> List[EvaluationScore]:
105
+ scores = {}
106
+ for evaluation in evaluations:
107
+ if evaluation.name not in scores:
108
+ scores[evaluation.name] = []
109
+ scores[evaluation.name].append(evaluation)
110
+
111
+ aggregated_results = [
112
+ self._aggregate_result(name, evals)
113
+ for name, evals in scores.items()
114
+ ]
115
+ return aggregated_results
116
+
117
+ def evaluate_sync(
118
+ self, conversation: str, scores: list[Score], n_rounds: int
119
+ ) -> List[EvaluationScore]:
120
+ with concurrent.futures.ThreadPoolExecutor(
121
+ max_workers=self.config.max_concurrency
122
+ ) as executor:
123
+ futures = [
124
+ executor.submit(self._sync_evaluate_once, conversation, score)
125
+ for _ in range(n_rounds)
126
+ for score in scores
127
+ ]
128
+ evaluations = [
129
+ f.result() for f in concurrent.futures.as_completed(futures)
130
+ ]
131
+ return self._aggregate_results(
132
+ [e for e in evaluations if e is not None]
133
+ )
134
+
135
+ async def evaluate_async(
136
+ self, conversation: str, scores: list[Score], n_rounds: int
137
+ ) -> List[EvaluationScore]:
138
+ semaphore = asyncio.Semaphore(self.config.max_concurrency)
139
+
140
+ async def sem_task(score):
141
+ async with semaphore:
142
+ return await self._async_evaluate_once(conversation, score)
143
+
144
+ tasks = [sem_task(score) for _ in range(n_rounds) for score in scores]
145
+ evaluations = await asyncio.gather(*tasks)
146
+ return self._aggregate_results(
147
+ [e for e in evaluations if e is not None]
148
+ )
149
+
150
+ def evaluate(
151
+ self,
152
+ conversation: str,
153
+ scores: list[Score],
154
+ n_rounds: int = 5,
155
+ mode: Literal["sync", "async"] = "sync",
156
+ ) -> List[EvaluationScore]:
157
+ if mode == "async":
158
+ return asyncio.run(
159
+ self.evaluate_async(conversation, scores, n_rounds)
160
+ )
161
+ return self.evaluate_sync(conversation, scores, n_rounds)
@@ -0,0 +1,14 @@
1
+ PROMPT_TEMPLATE = (
2
+ "Your evaluation task is: {requirements}\n\n"
3
+ "Please perform step-by-step reasoning to reach your judgment.\n\n"
4
+ "Strictly output your answer in the following JSON format:\n"
5
+ '{{"judgment": bool, "reasoning": "string"}}\n\n'
6
+ "Do not output anything else.\n\n"
7
+ "Here is the conversation to evaluate:\n"
8
+ "{conversation}"
9
+ )
10
+
11
+ PRESET_PROMPT = {
12
+ "task_completion": "Evaluate whether the model's output completely fulfills the user's task requirements.",
13
+ "instruction_adherence": "Evaluate whether the model's output strictly follows the user's instructions without omissions, deviations, or hallucinations.",
14
+ }
@@ -0,0 +1,8 @@
1
+ from enum import Enum
2
+
3
+
4
+ class Score(str, Enum):
5
+ """Enum for score types."""
6
+
7
+ task_completion = "task_completion"
8
+ instruction_adherence = "instruction_adherence"
@@ -1,6 +1,7 @@
1
1
  import divi
2
2
  from divi.services.auth import init as init_auth
3
- from divi.services.core import init as init_core
3
+
4
+ # from divi.services.core import init as init_core
4
5
  from divi.services.datapark import init as init_datapark
5
6
 
6
7
 
@@ -1,4 +1,5 @@
1
1
  from typing_extensions import Optional
2
+
2
3
  import divi
3
4
  from divi.services import init as init_services
4
5
  from divi.session import Session, SessionExtra
@@ -6,7 +7,7 @@ from divi.signals.trace import Span
6
7
  from divi.signals.trace.trace import Trace
7
8
 
8
9
 
9
- def init_session(name: Optional[str]=None) -> Session:
10
+ def init_session(name: Optional[str] = None) -> Session:
10
11
  """init initializes the services and the Run"""
11
12
  init_services()
12
13
  session = Session(name=name)
@@ -29,7 +30,9 @@ def setup(
29
30
 
30
31
  # init the session if not already initialized
31
32
  if not divi._session:
32
- divi._session = init_session(name=session_extra.get('session_name') or span.name)
33
+ divi._session = init_session(
34
+ name=session_extra.get("session_name") or span.name
35
+ )
33
36
 
34
37
  # setup trace
35
38
  trace = session_extra.get("trace") or Trace(divi._session.id, span.name)
@@ -13,7 +13,7 @@
13
13
  "devDependencies": {
14
14
  "@biomejs/biome": "1.9.4",
15
15
  "@workspace/typescript-config": "workspace:*",
16
- "turbo": "^2.5.0",
16
+ "turbo": "^2.5.2",
17
17
  "typescript": "5.7.3",
18
18
  "ultracite": "^4.2.1"
19
19
  },