divi 0.0.1.dev19__tar.gz → 0.0.1.dev23__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 (232) hide show
  1. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/PKG-INFO +1 -1
  2. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/graphql/package.json +1 -1
  3. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/graphql/src/datasources/datapark-api.ts +18 -1
  4. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/graphql/src/resolvers.ts +13 -0
  5. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/graphql/src/schema.graphql +22 -0
  6. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/graphql/src/types/types.d.ts +41 -0
  7. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/@modal/(.)traces/[id]/page.tsx +1 -1
  8. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/api-keys/actions.ts +3 -2
  9. divi-0.0.1.dev23/apps/web/app/dashboard/api-keys/layout.tsx +29 -0
  10. {divi-0.0.1.dev19/apps/web → divi-0.0.1.dev23/apps/web/app/dashboard}/components/app-sidebar.tsx +9 -10
  11. {divi-0.0.1.dev19/apps/web → divi-0.0.1.dev23/apps/web/app/dashboard}/components/nav-secondary.tsx +1 -2
  12. {divi-0.0.1.dev19/apps/web → divi-0.0.1.dev23/apps/web/app/dashboard}/components/nav-user.tsx +0 -1
  13. {divi-0.0.1.dev19/apps/web → divi-0.0.1.dev23/apps/web/app/dashboard}/components/site-header.tsx +1 -1
  14. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/layout.tsx +5 -6
  15. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/settings/account/page.tsx +1 -1
  16. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/settings/appearance/page.tsx +1 -1
  17. {divi-0.0.1.dev19/apps/web → divi-0.0.1.dev23/apps/web/app/dashboard/settings}/components/sidebar-nav.tsx +0 -1
  18. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/settings/layout.tsx +1 -2
  19. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/settings/page.tsx +1 -1
  20. divi-0.0.1.dev23/apps/web/app/dashboard/traces/(children)/[id]/components/Span.tsx +161 -0
  21. {divi-0.0.1.dev19/apps/web → divi-0.0.1.dev23/apps/web/app/dashboard/traces/(children)/[id]}/components/responsive-resizable.tsx +9 -2
  22. {divi-0.0.1.dev19/apps/web → divi-0.0.1.dev23/apps/web/app/dashboard/traces/(children)/[id]}/components/trace-board.tsx +2 -5
  23. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/traces/(children)/[id]/page.tsx +1 -1
  24. divi-0.0.1.dev23/apps/web/app/dashboard/traces/(overview)/layout.tsx +26 -0
  25. divi-0.0.1.dev23/apps/web/app/dashboard/usages/actions.ts +73 -0
  26. divi-0.0.1.dev23/apps/web/app/dashboard/usages/components/usage-board.tsx +74 -0
  27. divi-0.0.1.dev23/apps/web/app/dashboard/usages/components/usage-chart.tsx +205 -0
  28. divi-0.0.1.dev23/apps/web/app/dashboard/usages/layout.tsx +26 -0
  29. divi-0.0.1.dev23/apps/web/app/dashboard/usages/page.tsx +29 -0
  30. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/home/components/home-header.tsx +2 -2
  31. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/login/page.tsx +2 -2
  32. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/signup/page.tsx +1 -1
  33. divi-0.0.1.dev23/apps/web/components/Highter.tsx +19 -0
  34. divi-0.0.1.dev23/apps/web/components/calendar.tsx +84 -0
  35. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/components/data-table-view-options.tsx +2 -1
  36. divi-0.0.1.dev23/apps/web/components/date-picker.tsx +101 -0
  37. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/lib/server/openai.ts +1 -1
  38. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/lib/types/span.d.ts +1 -1
  39. divi-0.0.1.dev23/apps/web/lib/types/usage.d.ts +9 -0
  40. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/middleware.ts +1 -1
  41. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/package.json +9 -5
  42. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/__init__.py +1 -1
  43. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/decorators/obs_openai.py +0 -1
  44. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/decorators/observable.py +11 -32
  45. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/services/datapark/datapark.py +19 -7
  46. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/session/session.py +3 -3
  47. divi-0.0.1.dev23/divi/session/setup.py +45 -0
  48. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/signals/trace/trace.py +18 -18
  49. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/go.work.sum +1 -0
  50. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/package.json +2 -2
  51. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/pnpm-lock.yaml +715 -581
  52. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/pnpm-workspace.yaml +2 -0
  53. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/go.mod +5 -5
  54. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/go.sum +10 -10
  55. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/internal/app/datapark/handler/metric.go +3 -1
  56. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/internal/app/datapark/handler/openai.go +48 -2
  57. divi-0.0.1.dev23/services/internal/app/datapark/handler/usage.go +127 -0
  58. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/internal/app/datapark/router/router.go +4 -0
  59. divi-0.0.1.dev23/services/internal/pkg/model/usage.go +46 -0
  60. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/uv.lock +0 -2
  61. divi-0.0.1.dev19/apps/web/app/dashboard/api-keys/layout.tsx +0 -26
  62. divi-0.0.1.dev19/apps/web/app/dashboard/page.tsx +0 -15
  63. divi-0.0.1.dev19/apps/web/app/dashboard/traces/(overview)/layout.tsx +0 -23
  64. divi-0.0.1.dev19/apps/web/app/dashboard/usages/page.tsx +0 -15
  65. divi-0.0.1.dev19/apps/web/components/chart-area-interactive.tsx +0 -292
  66. divi-0.0.1.dev19/apps/web/components/section-cards.tsx +0 -102
  67. divi-0.0.1.dev19/divi/session/setup.py +0 -62
  68. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/.air.toml +0 -0
  69. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/.dockerignore +0 -0
  70. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/.github/dependabot.yml +0 -0
  71. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/.gitignore +0 -0
  72. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/LICENSE +0 -0
  73. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/README.md +0 -0
  74. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/README.md +0 -0
  75. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/docs/README.md +0 -0
  76. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/docs/concepts/session.mdx +0 -0
  77. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/docs/development/roadmap.mdx +0 -0
  78. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/docs/docs.json +0 -0
  79. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/docs/favicon.ico +0 -0
  80. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/docs/images/researcher-angel.png +0 -0
  81. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/docs/images/scholar-angel.png +0 -0
  82. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/docs/introduction.mdx +0 -0
  83. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/docs/package.json +0 -0
  84. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/docs/quickstart/trace.mdx +0 -0
  85. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/docs/snippets/snippet-intro.mdx +0 -0
  86. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/docs/tutorials/openai.mdx +0 -0
  87. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/graphql/Dockerfile +0 -0
  88. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/graphql/README.md +0 -0
  89. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/graphql/codegen.ts +0 -0
  90. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/graphql/src/datasources/auth-api.ts +0 -0
  91. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/graphql/src/index.ts +0 -0
  92. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/graphql/src/types/context.d.ts +0 -0
  93. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/graphql/src/types/response.d.ts +0 -0
  94. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/graphql/tsconfig.json +0 -0
  95. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/.gitignore +0 -0
  96. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/README.md +0 -0
  97. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/@modal/default.tsx +0 -0
  98. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/api-keys/components/columns.tsx +0 -0
  99. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/api-keys/components/create-dialog.tsx +0 -0
  100. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/api-keys/components/data-table-cell-viewer.tsx +0 -0
  101. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/api-keys/components/data-table-toolbar.tsx +0 -0
  102. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/api-keys/components/data-table.tsx +0 -0
  103. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/api-keys/components/delete-dialog.tsx +0 -0
  104. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/api-keys/data/data.tsx +0 -0
  105. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/api-keys/data/schema.ts +0 -0
  106. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/api-keys/page.tsx +0 -0
  107. {divi-0.0.1.dev19/apps/web → divi-0.0.1.dev23/apps/web/app/dashboard}/components/nav-main.tsx +0 -0
  108. {divi-0.0.1.dev19/apps/web → divi-0.0.1.dev23/apps/web/app/dashboard/settings/account}/components/account-form.tsx +0 -0
  109. {divi-0.0.1.dev19/apps/web → divi-0.0.1.dev23/apps/web/app/dashboard/settings/appearance}/components/appearance-form.tsx +0 -0
  110. {divi-0.0.1.dev19/apps/web → divi-0.0.1.dev23/apps/web/app/dashboard/settings}/components/profile-form.tsx +0 -0
  111. {divi-0.0.1.dev19/apps/web → divi-0.0.1.dev23/apps/web/app/dashboard/traces/(children)/[id]}/components/trace-chart.tsx +0 -0
  112. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/traces/(overview)/components/columns.tsx +0 -0
  113. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/traces/(overview)/components/data-table-row-action.tsx +0 -0
  114. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/traces/(overview)/components/data-table-toolbar.tsx +0 -0
  115. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/traces/(overview)/components/data-table.tsx +0 -0
  116. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/traces/(overview)/data/data.tsx +0 -0
  117. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/traces/(overview)/data/schema.ts +0 -0
  118. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/dashboard/traces/(overview)/page.tsx +0 -0
  119. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/favicon.ico +0 -0
  120. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/home/components/home-hero.tsx +0 -0
  121. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/home/page.tsx +0 -0
  122. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/layout.tsx +0 -0
  123. {divi-0.0.1.dev19/apps/web → divi-0.0.1.dev23/apps/web/app/login}/components/login-form.tsx +0 -0
  124. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/app/page.tsx +0 -0
  125. {divi-0.0.1.dev19/apps/web → divi-0.0.1.dev23/apps/web/app/signup}/components/signup-form.tsx +0 -0
  126. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/components/ApolloWrapper.tsx +0 -0
  127. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/components/Modal.tsx +0 -0
  128. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/components/data-table-column-header.tsx +0 -0
  129. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/components/data-table-faceted-filter.tsx +0 -0
  130. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/components/data-table-pagination.tsx +0 -0
  131. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/components/data-table-row.tsx +0 -0
  132. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/components/mode-switcher.tsx +0 -0
  133. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/components/theme-provider.tsx +0 -0
  134. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/components.json +0 -0
  135. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/hooks/actionState.ts +0 -0
  136. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/hooks/apolloClient.ts +0 -0
  137. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/lib/callback/toast-callback.ts +0 -0
  138. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/lib/callback/with-callback.ts +0 -0
  139. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/lib/server/README.md +0 -0
  140. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/lib/server/auth.ts +0 -0
  141. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/lib/server/cookies.ts +0 -0
  142. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/lib/server/span.ts +0 -0
  143. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/lib/types/state.d.ts +0 -0
  144. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/lib/utils.ts +0 -0
  145. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/next-env.d.ts +0 -0
  146. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/next.config.ts +0 -0
  147. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/postcss.config.mjs +0 -0
  148. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/public/peeking-angel.png +0 -0
  149. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/public/thinking-angel.png +0 -0
  150. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/tsconfig.json +0 -0
  151. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/apps/web/vercel.json +0 -0
  152. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/biome.json +0 -0
  153. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/compose-dev.yml +0 -0
  154. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/config/config.py +0 -0
  155. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/decorators/__init__.py +0 -0
  156. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/proto/common/v1/common.proto +0 -0
  157. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/proto/common/v1/common_pb2.py +0 -0
  158. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/proto/common/v1/common_pb2.pyi +0 -0
  159. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/proto/core/health/v1/health_service.proto +0 -0
  160. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/proto/core/health/v1/health_service_pb2.py +0 -0
  161. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/proto/core/health/v1/health_service_pb2.pyi +0 -0
  162. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/proto/core/health/v1/health_service_pb2_grpc.py +0 -0
  163. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/proto/metric/v1/metric.proto +0 -0
  164. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/proto/metric/v1/metric_pb2.py +0 -0
  165. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/proto/metric/v1/metric_pb2.pyi +0 -0
  166. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/proto/trace/v1/trace.proto +0 -0
  167. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/proto/trace/v1/trace_pb2.py +0 -0
  168. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/proto/trace/v1/trace_pb2.pyi +0 -0
  169. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/services/__init__.py +0 -0
  170. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/services/auth/__init__.py +0 -0
  171. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/services/auth/auth.py +0 -0
  172. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/services/auth/init.py +0 -0
  173. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/services/auth/tokman.py +0 -0
  174. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/services/core/__init__.py +0 -0
  175. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/services/core/core.py +0 -0
  176. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/services/core/finish.py +0 -0
  177. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/services/core/init.py +0 -0
  178. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/services/datapark/__init__.py +0 -0
  179. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/services/datapark/init.py +0 -0
  180. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/services/finish.py +0 -0
  181. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/services/init.py +0 -0
  182. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/services/service.py +0 -0
  183. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/session/__init__.py +0 -0
  184. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/session/teardown.py +0 -0
  185. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/signals/__init__.py +0 -0
  186. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/signals/trace/__init__.py +0 -0
  187. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/divi/utils.py +0 -0
  188. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/docker-compose.yml +0 -0
  189. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/docs/README.md +0 -0
  190. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/docs/developer_tools.md +0 -0
  191. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/docs/images/architecture.svg +0 -0
  192. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/docs/images/favicon.ico +0 -0
  193. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/docs/images/og-image.png +0 -0
  194. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/docs/images/storage.svg +0 -0
  195. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/docs/package_readme.md +0 -0
  196. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/go.work +0 -0
  197. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/hatch.toml +0 -0
  198. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/packages/README.md +0 -0
  199. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/pyproject.toml +0 -0
  200. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/scripts/README.md +0 -0
  201. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/scripts/hatch_build.py +0 -0
  202. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/scripts/key_build.py +0 -0
  203. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/scripts/proto_build.py +0 -0
  204. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/README.md +0 -0
  205. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/internal/app/auth/handler/api.go +0 -0
  206. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/internal/app/auth/handler/api_key.go +0 -0
  207. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/internal/app/auth/handler/auth.go +0 -0
  208. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/internal/app/auth/handler/user.go +0 -0
  209. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/internal/app/auth/router/router.go +0 -0
  210. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/internal/app/core/.keep +0 -0
  211. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/internal/app/datapark/handler/api.go +0 -0
  212. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/internal/app/datapark/handler/session.go +0 -0
  213. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/internal/app/datapark/handler/trace.go +0 -0
  214. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/internal/pkg/auth/auth.go +0 -0
  215. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/internal/pkg/auth/middleware.go +0 -0
  216. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/internal/pkg/config/config.go +0 -0
  217. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/internal/pkg/database/connect.go +0 -0
  218. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/internal/pkg/database/database.go +0 -0
  219. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/internal/pkg/model/api_key.go +0 -0
  220. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/internal/pkg/model/openai.go +0 -0
  221. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/internal/pkg/model/session.go +0 -0
  222. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/internal/pkg/model/trace.go +0 -0
  223. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/internal/pkg/model/user.go +0 -0
  224. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/pb/common.pb.go +0 -0
  225. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/pb/health_service.pb.go +0 -0
  226. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/pb/health_service_grpc.pb.go +0 -0
  227. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/pb/metric.pb.go +0 -0
  228. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/services/pb/trace.pb.go +0 -0
  229. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/tests/__init__.py +0 -0
  230. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/tests/unit_tests/decorators/test_obs_openai.py +0 -0
  231. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/tests/unit_tests/decorators/test_observable.py +0 -0
  232. {divi-0.0.1.dev19 → divi-0.0.1.dev23}/turbo.json +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: divi
3
- Version: 0.0.1.dev19
3
+ Version: 0.0.1.dev23
4
4
  Summary: The Agent Platform for Observability & Evaluation
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.11
@@ -11,7 +11,7 @@
11
11
  },
12
12
  "dependencies": {
13
13
  "@apollo/datasource-rest": "^6.4.1",
14
- "@apollo/server": "^4.11.3",
14
+ "@apollo/server": "^4.12.0",
15
15
  "@apollo/utils.keyvaluecache": "^3.1.0",
16
16
  "graphql": "^16.10.0",
17
17
  "graphql-tag": "^2.12.6"
@@ -1,5 +1,5 @@
1
1
  import type { FetchResponse } from '@/types/response';
2
- import type { ChatInput, Span, Trace } from '@/types/types';
2
+ import type { ChatInput, Span, Trace, UsageResult } from '@/types/types';
3
3
  import { type AugmentedRequest, RESTDataSource } from '@apollo/datasource-rest';
4
4
  import type { KeyValueCache } from '@apollo/utils.keyvaluecache';
5
5
 
@@ -35,4 +35,21 @@ export class DataParkAPI extends RESTDataSource {
35
35
  `/api/v1/chat/completions/${spanId}/input`
36
36
  );
37
37
  }
38
+
39
+ async getCompletionUsage(
40
+ startTime: number,
41
+ endTime: number | undefined,
42
+ groupBy: string | undefined
43
+ ) {
44
+ return await this.get<FetchResponse<UsageResult[]>>(
45
+ '/api/usage/completions',
46
+ {
47
+ params: {
48
+ start_time: startTime.toString(),
49
+ end_time: endTime?.toString(),
50
+ group_by: groupBy,
51
+ },
52
+ }
53
+ );
54
+ }
38
55
  }
@@ -29,6 +29,19 @@ export const resolvers: Resolvers = {
29
29
  chat_input: async (_, { span_id }, { dataSources }) => {
30
30
  return (await dataSources.dataparkAPI.getChatInput(span_id)).data;
31
31
  },
32
+ completion_usage: async (
33
+ _,
34
+ { start_time, end_time, group_by },
35
+ { dataSources }
36
+ ) => {
37
+ return (
38
+ await dataSources.dataparkAPI.getCompletionUsage(
39
+ start_time,
40
+ end_time ?? undefined,
41
+ group_by ?? undefined
42
+ )
43
+ ).data;
44
+ },
32
45
  },
33
46
  Mutation: {
34
47
  createAPIKey: async (_, { name }, { dataSources }) => {
@@ -14,6 +14,18 @@ type Query {
14
14
  spans(trace_id: ID!): [Span!]
15
15
  "Fetch openai input by span id"
16
16
  chat_input(span_id: ID!): ChatInput
17
+ "Fetch completion usages"
18
+ completion_usage(
19
+ start_time: Int!
20
+ end_time: Int
21
+ group_by: GroupingKey
22
+ ): [UsageResult!]
23
+ }
24
+
25
+ "GroupingKey is an enum that represents the key used to group usage results"
26
+ enum GroupingKey {
27
+ date
28
+ model
17
29
  }
18
30
 
19
31
  "NullTime is a custom scalar type that represents a time value that can be null"
@@ -54,6 +66,7 @@ type Trace {
54
66
  session_id: ID!
55
67
  }
56
68
 
69
+ "Kind is an enum that represents the type of span"
57
70
  enum Kind {
58
71
  SPAN_KIND_FUNCTION
59
72
  SPAN_KIND_LLM
@@ -91,6 +104,15 @@ type MessageInput {
91
104
  name: String
92
105
  }
93
106
 
107
+ "UsageResult is the result of a usage query"
108
+ type UsageResult {
109
+ input_tokens: Int!
110
+ output_tokens: Int!
111
+ total_tokens: Int!
112
+ model: String
113
+ date: Int
114
+ }
115
+
94
116
  "Mutation is a collection of mutations that can be made to the API"
95
117
  type Mutation {
96
118
  "Auth Mutations"
@@ -77,6 +77,12 @@ export type DeleteUserResponse = MutationResponse & {
77
77
  success: Scalars['Boolean']['output'];
78
78
  };
79
79
 
80
+ /** GroupingKey is an enum that represents the key used to group usage results */
81
+ export enum GroupingKey {
82
+ Date = 'date',
83
+ Model = 'model'
84
+ }
85
+
80
86
  /** KeyValue is a key-value pair */
81
87
  export type KeyValue = {
82
88
  __typename?: 'KeyValue';
@@ -84,6 +90,7 @@ export type KeyValue = {
84
90
  value: Scalars['String']['output'];
85
91
  };
86
92
 
93
+ /** Kind is an enum that represents the type of span */
87
94
  export enum Kind {
88
95
  SpanKindFunction = 'SPAN_KIND_FUNCTION',
89
96
  SpanKindLlm = 'SPAN_KIND_LLM'
@@ -190,6 +197,8 @@ export type Query = {
190
197
  api_keys?: Maybe<Array<ApiKey>>;
191
198
  /** Fetch openai input by span id */
192
199
  chat_input?: Maybe<ChatInput>;
200
+ /** Fetch completion usages */
201
+ completion_usage?: Maybe<Array<UsageResult>>;
193
202
  /** Fetch current user */
194
203
  me: User;
195
204
  /** Fetch all spans by trace id */
@@ -207,6 +216,14 @@ export type QueryChat_InputArgs = {
207
216
  };
208
217
 
209
218
 
219
+ /** Query is a collection of queries that can be made to the API */
220
+ export type QueryCompletion_UsageArgs = {
221
+ end_time?: InputMaybe<Scalars['Int']['input']>;
222
+ group_by?: InputMaybe<GroupingKey>;
223
+ start_time: Scalars['Int']['input'];
224
+ };
225
+
226
+
210
227
  /** Query is a collection of queries that can be made to the API */
211
228
  export type QuerySpansArgs = {
212
229
  trace_id: Scalars['ID']['input'];
@@ -274,6 +291,16 @@ export type UpdateUserResponse = MutationResponse & {
274
291
  success: Scalars['Boolean']['output'];
275
292
  };
276
293
 
294
+ /** UsageResult is the result of a usage query */
295
+ export type UsageResult = {
296
+ __typename?: 'UsageResult';
297
+ date?: Maybe<Scalars['Int']['output']>;
298
+ input_tokens: Scalars['Int']['output'];
299
+ model?: Maybe<Scalars['String']['output']>;
300
+ output_tokens: Scalars['Int']['output'];
301
+ total_tokens: Scalars['Int']['output'];
302
+ };
303
+
277
304
  /** User is a registered user of the application */
278
305
  export type User = {
279
306
  __typename?: 'User';
@@ -367,6 +394,7 @@ export type ResolversTypes = {
367
394
  CreateUserResponse: ResolverTypeWrapper<Omit<CreateUserResponse, 'data'> & { data?: Maybe<ResolversTypes['User']> }>;
368
395
  DeleteUserResponse: ResolverTypeWrapper<DeleteUserResponse>;
369
396
  Float: ResolverTypeWrapper<Scalars['Float']['output']>;
397
+ GroupingKey: GroupingKey;
370
398
  ID: ResolverTypeWrapper<Scalars['ID']['output']>;
371
399
  Int: ResolverTypeWrapper<Scalars['Int']['output']>;
372
400
  KeyValue: ResolverTypeWrapper<KeyValue>;
@@ -382,6 +410,7 @@ export type ResolversTypes = {
382
410
  Trace: ResolverTypeWrapper<Trace>;
383
411
  UpdateAPIKeyResponse: ResolverTypeWrapper<Omit<UpdateApiKeyResponse, 'data'> & { data?: Maybe<ResolversTypes['APIKey']> }>;
384
412
  UpdateUserResponse: ResolverTypeWrapper<Omit<UpdateUserResponse, 'data'> & { data?: Maybe<ResolversTypes['User']> }>;
413
+ UsageResult: ResolverTypeWrapper<UsageResult>;
385
414
  User: ResolverTypeWrapper<UserModel>;
386
415
  };
387
416
 
@@ -409,6 +438,7 @@ export type ResolversParentTypes = {
409
438
  Trace: Trace;
410
439
  UpdateAPIKeyResponse: Omit<UpdateApiKeyResponse, 'data'> & { data?: Maybe<ResolversParentTypes['APIKey']> };
411
440
  UpdateUserResponse: Omit<UpdateUserResponse, 'data'> & { data?: Maybe<ResolversParentTypes['User']> };
441
+ UsageResult: UsageResult;
412
442
  User: UserModel;
413
443
  };
414
444
 
@@ -504,6 +534,7 @@ export type QueryResolvers<ContextType = DataSourceContext, ParentType extends R
504
534
  all_traces?: Resolver<Maybe<Array<ResolversTypes['Trace']>>, ParentType, ContextType>;
505
535
  api_keys?: Resolver<Maybe<Array<ResolversTypes['APIKey']>>, ParentType, ContextType>;
506
536
  chat_input?: Resolver<Maybe<ResolversTypes['ChatInput']>, ParentType, ContextType, RequireFields<QueryChat_InputArgs, 'span_id'>>;
537
+ completion_usage?: Resolver<Maybe<Array<ResolversTypes['UsageResult']>>, ParentType, ContextType, RequireFields<QueryCompletion_UsageArgs, 'start_time'>>;
507
538
  me?: Resolver<ResolversTypes['User'], ParentType, ContextType>;
508
539
  spans?: Resolver<Maybe<Array<ResolversTypes['Span']>>, ParentType, ContextType, RequireFields<QuerySpansArgs, 'trace_id'>>;
509
540
  traces?: Resolver<Maybe<Array<ResolversTypes['Trace']>>, ParentType, ContextType, RequireFields<QueryTracesArgs, 'session_id'>>;
@@ -555,6 +586,15 @@ export type UpdateUserResponseResolvers<ContextType = DataSourceContext, ParentT
555
586
  __isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
556
587
  };
557
588
 
589
+ export type UsageResultResolvers<ContextType = DataSourceContext, ParentType extends ResolversParentTypes['UsageResult'] = ResolversParentTypes['UsageResult']> = {
590
+ date?: Resolver<Maybe<ResolversTypes['Int']>, ParentType, ContextType>;
591
+ input_tokens?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
592
+ model?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
593
+ output_tokens?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
594
+ total_tokens?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
595
+ __isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
596
+ };
597
+
558
598
  export type UserResolvers<ContextType = DataSourceContext, ParentType extends ResolversParentTypes['User'] = ResolversParentTypes['User']> = {
559
599
  api_keys?: Resolver<Maybe<Array<ResolversTypes['APIKey']>>, ParentType, ContextType>;
560
600
  email?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
@@ -582,6 +622,7 @@ export type Resolvers<ContextType = DataSourceContext> = {
582
622
  Trace?: TraceResolvers<ContextType>;
583
623
  UpdateAPIKeyResponse?: UpdateApiKeyResponseResolvers<ContextType>;
584
624
  UpdateUserResponse?: UpdateUserResponseResolvers<ContextType>;
625
+ UsageResult?: UsageResultResolvers<ContextType>;
585
626
  User?: UserResolvers<ContextType>;
586
627
  };
587
628
 
@@ -1,5 +1,5 @@
1
1
  import { ResponsiveDrawer } from '@/components/Modal';
2
- import { TraceBoard } from '@/components/trace-board';
2
+ import { TraceBoard } from '@/app/dashboard/traces/(children)/[id]/components/trace-board';
3
3
  import { getTraceChartData } from '@/lib/server/span';
4
4
 
5
5
  interface TraceModalPageProps {
@@ -13,12 +13,13 @@ import {
13
13
  import { GetMyApiKeysDocument } from '@workspace/graphql-client/src/auth/api-keys.generated';
14
14
  import type { ApiKey } from '@workspace/graphql-client/src/types.generated';
15
15
  import { revalidatePath } from 'next/cache';
16
+ import { cache } from 'react';
16
17
 
17
18
  /**
18
19
  * getAPIKeys action with graphql query
19
20
  * @description get current user's API keys
20
21
  */
21
- export async function getAPIKeys() {
22
+ export const getAPIKeys = cache(async () => {
22
23
  const context = await getAuthContext();
23
24
  if (!context) {
24
25
  return null;
@@ -28,7 +29,7 @@ export async function getAPIKeys() {
28
29
  context,
29
30
  });
30
31
  return data?.api_keys;
31
- }
32
+ });
32
33
 
33
34
  /**
34
35
  * createAPIKey action with graphql mutation
@@ -0,0 +1,29 @@
1
+ import { ScrollArea } from '@workspace/ui/components/scroll-area';
2
+ import { Separator } from '@workspace/ui/components/separator';
3
+ import type React from 'react';
4
+ import { CreateDialog } from './components/create-dialog';
5
+
6
+ interface APIKeysLayoutProps {
7
+ children: React.ReactNode;
8
+ }
9
+
10
+ export default function APIKeysLayout({ children }: APIKeysLayoutProps) {
11
+ return (
12
+ <div className="h-full space-y-3 overflow-y-auto py-3">
13
+ <ScrollArea className="max-h-full">
14
+ <div className="flex items-center justify-between px-6">
15
+ <h1 className=" text-xl tracking-tight">API Keys</h1>
16
+ <CreateDialog />
17
+ </div>
18
+ <Separator className="my-3" />
19
+ <div className="px-6">
20
+ <p className="text-muted-foreground text-sm">
21
+ As a owner of this account, you can view and manage all API keys in
22
+ this account.
23
+ </p>
24
+ <div className="my-6">{children}</div>
25
+ </div>
26
+ </ScrollArea>
27
+ </div>
28
+ );
29
+ }
@@ -1,13 +1,9 @@
1
1
  'use client';
2
2
 
3
- import { NavMain } from '@/components/nav-main';
4
- import { NavSecondary } from '@/components/nav-secondary';
5
- import { NavUser } from '@/components/nav-user';
6
3
  import {
7
4
  IconBinaryTree,
8
5
  IconBook,
9
6
  IconCurrencyDollar,
10
- IconDashboard,
11
7
  IconKey,
12
8
  IconSettings,
13
9
  } from '@tabler/icons-react';
@@ -23,6 +19,9 @@ import {
23
19
  } from '@workspace/ui/components/sidebar';
24
20
  import Link from 'next/link';
25
21
  import type * as React from 'react';
22
+ import { NavMain } from './nav-main';
23
+ import { NavSecondary } from './nav-secondary';
24
+ import { NavUser } from './nav-user';
26
25
 
27
26
  const data = {
28
27
  user: {
@@ -31,11 +30,11 @@ const data = {
31
30
  avatar: '/thinking-angel.png',
32
31
  },
33
32
  navMain: [
34
- {
35
- title: 'Overview',
36
- url: '/dashboard',
37
- icon: IconDashboard,
38
- },
33
+ // {
34
+ // title: 'Overview',
35
+ // url: '/dashboard',
36
+ // icon: IconDashboard,
37
+ // },
39
38
  {
40
39
  title: 'Trace',
41
40
  url: '/dashboard/traces',
@@ -82,7 +81,7 @@ export function AppSidebar({
82
81
  asChild
83
82
  className="data-[slot=sidebar-menu-button]:!p-1.5"
84
83
  >
85
- <Link href="/">
84
+ <Link href="/home">
86
85
  <span className="text-xl">😇</span>
87
86
  <span className="font-semibold text-base">Divine Agent</span>
88
87
  </Link>
@@ -1,6 +1,5 @@
1
1
  import type { Icon } from '@tabler/icons-react';
2
2
  import type * as React from 'react';
3
-
4
3
  import {
5
4
  SidebarGroup,
6
5
  SidebarGroupContent,
@@ -27,7 +26,7 @@ export function NavSecondary({
27
26
  {items.map((item) => (
28
27
  <SidebarMenuItem key={item.title}>
29
28
  <SidebarMenuButton asChild>
30
- <Link href={item.url}>
29
+ <Link href={item.url} passHref>
31
30
  <item.icon />
32
31
  <span>{item.title}</span>
33
32
  </Link>
@@ -4,7 +4,6 @@ import {
4
4
  IconUserCircle,
5
5
  } from '@tabler/icons-react';
6
6
  import type { User } from '@workspace/graphql-client/src/types.generated';
7
-
8
7
  import {
9
8
  Avatar,
10
9
  AvatarFallback,
@@ -1,6 +1,6 @@
1
1
  import { SiGithub } from '@icons-pack/react-simple-icons';
2
2
  import { SidebarTrigger } from '@workspace/ui/components/sidebar';
3
- import { ModeSwitcher } from './mode-switcher';
3
+ import { ModeSwitcher } from '@/components/mode-switcher';
4
4
 
5
5
  export function SiteHeader() {
6
6
  return (
@@ -1,5 +1,5 @@
1
- import { AppSidebar } from '@/components/app-sidebar';
2
- import { SiteHeader } from '@/components/site-header';
1
+ import { AppSidebar } from './components/app-sidebar';
2
+ import { SiteHeader } from './components/site-header';
3
3
  import { getCurrentUser } from '@/lib/server/auth';
4
4
  import { deleteSessionTokenCookie } from '@/lib/server/cookies';
5
5
  import {
@@ -38,6 +38,7 @@ export default async function DashboardLayout({
38
38
  return (
39
39
  <SidebarProvider
40
40
  defaultOpen={defaultOpen}
41
+ className="max-h-screen"
41
42
  style={
42
43
  {
43
44
  '--sidebar-width': 'calc(var(--spacing) * 58)',
@@ -47,10 +48,8 @@ export default async function DashboardLayout({
47
48
  <AppSidebar variant="inset" user={user} signoutAction={signout} />
48
49
  <SidebarInset>
49
50
  <SiteHeader />
50
- <div className="flex flex-1 flex-col">
51
- {modal}
52
- {children}
53
- </div>
51
+ {modal}
52
+ {children}
54
53
  </SidebarInset>
55
54
  </SidebarProvider>
56
55
  );
@@ -1,4 +1,4 @@
1
- import { AccountForm } from '@/components/account-form';
1
+ import { AccountForm } from './components/account-form';
2
2
  import { getClient } from '@/hooks/apolloClient';
3
3
  import { getCurrentUser } from '@/lib/server/auth';
4
4
  import { getAuthContext } from '@/lib/server/auth';
@@ -1,4 +1,4 @@
1
- import { AppearanceForm } from '@/components/appearance-form';
1
+ import { AppearanceForm } from './components/appearance-form';
2
2
  import { Separator } from '@workspace/ui/components/separator';
3
3
 
4
4
  export default function SettingsAppearancePage() {
@@ -2,7 +2,6 @@
2
2
 
3
3
  import Link from 'next/link';
4
4
  import { usePathname } from 'next/navigation';
5
-
6
5
  import { buttonVariants } from '@workspace/ui/components/button';
7
6
  import { cn } from '@workspace/ui/lib/utils';
8
7
  import type React from 'react';
@@ -1,6 +1,5 @@
1
1
  import type { Metadata } from 'next';
2
-
3
- import { SidebarNav } from '@/components/sidebar-nav';
2
+ import { SidebarNav } from './components/sidebar-nav';
4
3
  import { Separator } from '@workspace/ui/components/separator';
5
4
  import type React from 'react';
6
5
 
@@ -1,4 +1,4 @@
1
- import { ProfileForm } from '@/components/profile-form';
1
+ import { ProfileForm } from './components/profile-form';
2
2
  import { getCurrentUser } from '@/lib/server/auth';
3
3
  import { Separator } from '@workspace/ui/components/separator';
4
4
 
@@ -0,0 +1,161 @@
1
+ import type { ExtendedSpan } from '@/lib/types/span';
2
+ import { formatDate } from '@/lib/utils';
3
+ import {
4
+ Accordion,
5
+ AccordionContent,
6
+ AccordionItem,
7
+ AccordionTrigger,
8
+ } from '@workspace/ui/components/accordion';
9
+ import { Badge } from '@workspace/ui/components/badge';
10
+ import {
11
+ Card,
12
+ CardContent,
13
+ CardDescription,
14
+ CardHeader,
15
+ CardTitle,
16
+ } from '@workspace/ui/components/card';
17
+ import { Timer } from 'lucide-react';
18
+ import type * as React from 'react';
19
+ import Highlighter from '@/components/Highter';
20
+
21
+ interface SpanProps {
22
+ span: ExtendedSpan;
23
+ }
24
+
25
+ export function Span({ span }: SpanProps) {
26
+ const messages = span.input?.messages ?? [];
27
+ const choices = span.completion?.choices ?? [];
28
+ return (
29
+ <>
30
+ <GeneralInfo span={span} />
31
+ <Accordion
32
+ type="multiple"
33
+ defaultValue={['properties', 'Input', 'Output']}
34
+ >
35
+ <AccordionProperties span={span} />
36
+ <AccordionJsonCards name="Input" datas={messages} />
37
+ <AccordionJsonCards name="Output" datas={choices} />
38
+ </Accordion>
39
+ </>
40
+ );
41
+ }
42
+
43
+ function GeneralInfo({ span }: SpanProps) {
44
+ return (
45
+ <div className="flex flex-col gap-3 border-b p-4">
46
+ <div className="flex items-center justify-between text-text-primary">
47
+ <span className="font-medium">{span.name}</span>
48
+ </div>
49
+ <div className="flex gap-3">
50
+ <Badge variant="secondary">{span.kind}</Badge>
51
+ <Badge variant="outline">
52
+ <Timer />
53
+ {span.duration} ms
54
+ </Badge>
55
+ </div>
56
+ </div>
57
+ );
58
+ }
59
+
60
+ function AccordionProperties({ span }: SpanProps) {
61
+ // TODO select the properties to show
62
+ const startTime = formatDate(span.start_time);
63
+ const endTime = formatDate(span.end_time);
64
+ const usage = span.completion?.usage;
65
+ // input should pop messages
66
+ const { messages, ...inputs } = span.input ?? {};
67
+ // input parameters display standard: key not starting with __ and value not null or undefined
68
+ const filteredInputs = Object.entries(inputs).filter(
69
+ ([key, value]) =>
70
+ value !== null && value !== undefined && !key.startsWith('__')
71
+ );
72
+
73
+ return (
74
+ <AccordionItem className="px-4" value="properties">
75
+ <AccordionTrigger className="hover:no-underline">
76
+ Properties
77
+ </AccordionTrigger>
78
+ <AccordionContent>
79
+ <div className="flex flex-col gap-2">
80
+ {filteredInputs.length > 0 && (
81
+ <PropertyCard title="Patameters">
82
+ {filteredInputs.map(([key, value]) => (
83
+ <PropertyItem key={key} label={key} value={value} />
84
+ ))}
85
+ </PropertyCard>
86
+ )}
87
+ {usage && (
88
+ <PropertyCard title="Usages">
89
+ <PropertyItem label="Prompt Tokens" value={usage.prompt_tokens} />
90
+ <PropertyItem
91
+ label="Completion Tokens"
92
+ value={usage.completion_tokens}
93
+ />
94
+ <PropertyItem label="Total Tokens" value={usage.total_tokens} />
95
+ </PropertyCard>
96
+ )}
97
+ <PropertyCard title="Metadatas">
98
+ <PropertyItem label="Start Time" value={startTime} />
99
+ <PropertyItem label="End Time" value={endTime} />
100
+ </PropertyCard>
101
+ </div>
102
+ </AccordionContent>
103
+ </AccordionItem>
104
+ );
105
+ }
106
+
107
+ function PropertyCard({
108
+ title,
109
+ description,
110
+ children,
111
+ }: { title: string; description?: string; children: React.ReactNode }) {
112
+ return (
113
+ <Card className="w-full">
114
+ <CardHeader>
115
+ <CardTitle>{title}</CardTitle>
116
+ {description && <CardDescription> {description}</CardDescription>}
117
+ </CardHeader>
118
+ <CardContent className="flex flex-col gap-2">{children}</CardContent>
119
+ </Card>
120
+ );
121
+ }
122
+
123
+ function PropertyItem({
124
+ label,
125
+ value,
126
+ }: {
127
+ label: string;
128
+ value: string | number | boolean | null;
129
+ }) {
130
+ return (
131
+ <div className="flex items-center justify-between">
132
+ <span className="text-sm">{label}</span>
133
+ <span className="truncate font-light text-sm">{String(value)}</span>
134
+ </div>
135
+ );
136
+ }
137
+
138
+ interface AccordionCardsProps<T> {
139
+ name: string;
140
+ datas: T[];
141
+ }
142
+
143
+ function AccordionJsonCards<T>({ name, datas }: AccordionCardsProps<T>) {
144
+ return (
145
+ <AccordionItem value={name} className="px-4">
146
+ <AccordionTrigger className="hover:no-underline">{name}</AccordionTrigger>
147
+ <AccordionContent className="flex flex-col gap-3">
148
+ {datas.map((data, index) => (
149
+ <Card key={index}>
150
+ <CardContent>
151
+ <Highlighter
152
+ content={JSON.stringify(data, null, 2)}
153
+ language="json"
154
+ />
155
+ </CardContent>
156
+ </Card>
157
+ ))}
158
+ </AccordionContent>
159
+ </AccordionItem>
160
+ );
161
+ }
@@ -5,6 +5,7 @@ import {
5
5
  ResizablePanel,
6
6
  ResizablePanelGroup,
7
7
  } from '@workspace/ui/components/resizable';
8
+ import { ScrollArea } from '@workspace/ui/components/scroll-area';
8
9
  import { useIsMobile } from '@workspace/ui/hooks/use-mobile';
9
10
  import type { ReactNode } from 'react';
10
11
 
@@ -28,10 +29,16 @@ export function ResponsiveResizable({
28
29
  return (
29
30
  <ResizablePanelGroup direction={_direction}>
30
31
  <ResizablePanel defaultSize={50} minSize={25}>
31
- {first}
32
+ <div className="h-full overflow-y-auto">
33
+ <ScrollArea className="max-h-full">{first}</ScrollArea>
34
+ </div>
32
35
  </ResizablePanel>
33
36
  <ResizableHandle />
34
- <ResizablePanel defaultSize={50}>{second}</ResizablePanel>
37
+ <ResizablePanel defaultSize={50}>
38
+ <div className="h-full overflow-y-auto">
39
+ <ScrollArea className="max-h-full">{second}</ScrollArea>
40
+ </div>
41
+ </ResizablePanel>
35
42
  </ResizablePanelGroup>
36
43
  );
37
44
  }
@@ -2,6 +2,7 @@
2
2
 
3
3
  import type { ExtendedSpan } from '@/lib/types/span';
4
4
  import { useState } from 'react';
5
+ import { Span } from './Span';
5
6
  import { ResponsiveResizable } from './responsive-resizable';
6
7
  import { TraceWaterfallChart } from './trace-chart';
7
8
 
@@ -25,11 +26,7 @@ export function TraceBoard({ spans, direction }: TraceBoardProps) {
25
26
  selectAction={selectAction}
26
27
  />
27
28
  }
28
- second={
29
- <span className="font-semibold">
30
- {JSON.stringify(spans[index ?? 0])}
31
- </span>
32
- }
29
+ second={<Span span={spans[index ?? 0]} />}
33
30
  direction={direction}
34
31
  />
35
32
  );
@@ -1,4 +1,4 @@
1
- import { TraceBoard } from '@/components/trace-board';
1
+ import { TraceBoard } from './components/trace-board';
2
2
  import { getTraceChartData } from '@/lib/server/span';
3
3
 
4
4
  interface TracePageProps {