@zhijianma/studio 1.0.10

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 (235) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +158 -0
  3. package/bin/cli.js +7 -0
  4. package/dist/app/friday/args.py +65 -0
  5. package/dist/app/friday/hook.py +52 -0
  6. package/dist/app/friday/main.py +164 -0
  7. package/dist/app/friday/model.py +124 -0
  8. package/dist/app/friday/tool/agentscope_tools.py +159 -0
  9. package/dist/app/friday/tool/utils.py +161 -0
  10. package/dist/app/friday/utils/common.py +28 -0
  11. package/dist/app/friday/utils/connect.py +63 -0
  12. package/dist/app/friday/utils/constants.py +8 -0
  13. package/dist/app/requirements.txt +1 -0
  14. package/dist/public/assets/001-aaron-Bb4ZO8rt.js +1 -0
  15. package/dist/public/assets/001-little girl-CnyQBZ0k.js +1 -0
  16. package/dist/public/assets/001-man-16-BO6NLPD_.js +1 -0
  17. package/dist/public/assets/002-avatar-C3FPnFjo.js +1 -0
  18. package/dist/public/assets/002-man-15-DfiiX2xR.js +1 -0
  19. package/dist/public/assets/002-old man-D4L-hA2l.js +1 -0
  20. package/dist/public/assets/003-avatar-UMXD80xE.js +1 -0
  21. package/dist/public/assets/003-cat-Cgyj1qJU.js +1 -0
  22. package/dist/public/assets/003-woman-20-Dy0WdjIG.js +1 -0
  23. package/dist/public/assets/004-avatar-D6Aw4tpO.js +1 -0
  24. package/dist/public/assets/004-dog-DUajs1ZO.js +1 -0
  25. package/dist/public/assets/004-woman-19-D5go5okE.js +1 -0
  26. package/dist/public/assets/005-avatar-NNQ3sWMe.js +1 -0
  27. package/dist/public/assets/005-child-SN-FoL0R.js +1 -0
  28. package/dist/public/assets/005-woman-18-AedSRg8a.js +1 -0
  29. package/dist/public/assets/006-avatar-FD8IUNL_.js +1 -0
  30. package/dist/public/assets/006-grandpa-T90IdpYr.js +1 -0
  31. package/dist/public/assets/006-man-14-DuMA-IZ-.js +1 -0
  32. package/dist/public/assets/007-avatar-eSQZtpkg.js +1 -0
  33. package/dist/public/assets/007-grandson-DV7UWhrR.js +1 -0
  34. package/dist/public/assets/007-man-13-owFTee2M.js +1 -0
  35. package/dist/public/assets/008-avatar-B9Rcm8D2.js +1 -0
  36. package/dist/public/assets/008-grandmother-1-BrQNVu9I.js +1 -0
  37. package/dist/public/assets/008-teenager-ClYxB7sG.js +1 -0
  38. package/dist/public/assets/009-avatar-DNSTEyOZ.js +1 -0
  39. package/dist/public/assets/009-grandfather-1-CPOn7LN0.js +1 -0
  40. package/dist/public/assets/009-grandmother-BAW_dEQC.js +1 -0
  41. package/dist/public/assets/010-avatar-CRXWH-A0.js +1 -0
  42. package/dist/public/assets/010-boy-1-C21LhAEr.js +1 -0
  43. package/dist/public/assets/011-woman-17-CI0UoPMR.js +1 -0
  44. package/dist/public/assets/012-avatar-BO5j-gGw.js +1 -0
  45. package/dist/public/assets/012-boy-T-hL8z9d.js +1 -0
  46. package/dist/public/assets/012-niece-M-tDMWMW.js +1 -0
  47. package/dist/public/assets/013-avatar-BTyOVKVo.js +1 -0
  48. package/dist/public/assets/013-granddaughter-D4VonRL-.js +1 -0
  49. package/dist/public/assets/013-woman-16-CuR7_ppw.js +1 -0
  50. package/dist/public/assets/014-avatar-DAW_Hvos.js +1 -0
  51. package/dist/public/assets/014-man-k8AXOF1Q.js +1 -0
  52. package/dist/public/assets/014-nurse-DnVigtmM.js +1 -0
  53. package/dist/public/assets/015-avatar-AxHR3j7h.js +1 -0
  54. package/dist/public/assets/015-woman-15-rDPwBxxc.js +1 -0
  55. package/dist/public/assets/015-woman-B71QRPrr.js +1 -0
  56. package/dist/public/assets/016-avatar-BVbMUisT.js +1 -0
  57. package/dist/public/assets/016-boy-BV_jzAu3.js +1 -0
  58. package/dist/public/assets/016-woman-14-D08zoPt9.js +1 -0
  59. package/dist/public/assets/017-gaming-BEpEpa1H.js +1 -0
  60. package/dist/public/assets/017-superpower-9xQAqiKN.js +1 -0
  61. package/dist/public/assets/017-uncle-EB1lmqAo.js +1 -0
  62. package/dist/public/assets/017-woman-13-BFsTAnGR.js +1 -0
  63. package/dist/public/assets/018-avatar-CnCLJXqW.js +1 -0
  64. package/dist/public/assets/018-young-QpIX6g3z.js +1 -0
  65. package/dist/public/assets/019-gaming-Dz5tR0Te.js +1 -0
  66. package/dist/public/assets/019-man-12-DiRb1dri.js +1 -0
  67. package/dist/public/assets/019-nephew-tXAgA9cr.js +1 -0
  68. package/dist/public/assets/020-avatar-Djtnu7jj.js +1 -0
  69. package/dist/public/assets/020-man-11-BNIZQyX4.js +1 -0
  70. package/dist/public/assets/020-young woman-BzklF8tq.js +1 -0
  71. package/dist/public/assets/021-aunt-CX9ikaTy.js +1 -0
  72. package/dist/public/assets/021-avatar-DP2sODK2.js +1 -0
  73. package/dist/public/assets/021-superhero-CIWREXp0.js +1 -0
  74. package/dist/public/assets/021-wizard-Dc9X50m_.js +1 -0
  75. package/dist/public/assets/021-woman-12-n9ipJK5z.js +1 -0
  76. package/dist/public/assets/022-father-B1_-ZTn1.js +1 -0
  77. package/dist/public/assets/022-woman-11-BUCsm06E.js +1 -0
  78. package/dist/public/assets/023-avatar-TeJ6vGqs.js +1 -0
  79. package/dist/public/assets/023-ghost-BYvGsa7H.js +1 -0
  80. package/dist/public/assets/023-man-10-Dfii-GE1.js +1 -0
  81. package/dist/public/assets/023-uncle-DoAMe1Iy.js +1 -0
  82. package/dist/public/assets/024-gaming-5ovd4aeT.js +1 -0
  83. package/dist/public/assets/024-man-9-CEenp_2W.js +1 -0
  84. package/dist/public/assets/024-prince-Fx3eCiNX.js +1 -0
  85. package/dist/public/assets/024-uncle-B6tqhqxU.js +1 -0
  86. package/dist/public/assets/025-gaming-CdlTp3Ub.js +1 -0
  87. package/dist/public/assets/025-man-8-Cfp6jNt4.js +1 -0
  88. package/dist/public/assets/025-man-BxhR-XTO.js +1 -0
  89. package/dist/public/assets/025-princess-Di5TdSnG.js +1 -0
  90. package/dist/public/assets/026-avatar-DojOPRVd.js +1 -0
  91. package/dist/public/assets/026-dad-CHaoMWM5.js +1 -0
  92. package/dist/public/assets/026-owl-Dl-UtZM8.js +1 -0
  93. package/dist/public/assets/026-woman-10-CywXJiaj.js +1 -0
  94. package/dist/public/assets/027-avatar-CrEyLmOb.js +1 -0
  95. package/dist/public/assets/027-girl-Box_GaMO.js +1 -0
  96. package/dist/public/assets/028-gaming-CmOZ2uGp.js +1 -0
  97. package/dist/public/assets/028-mom-tEacX7K4.js +1 -0
  98. package/dist/public/assets/028-woman-9-C1oq4sFk.js +1 -0
  99. package/dist/public/assets/029-boy-CVg6oMuZ.js +1 -0
  100. package/dist/public/assets/029-man-7-C4eeEeTQ.js +1 -0
  101. package/dist/public/assets/030-elf-C8vikAvx.js +1 -0
  102. package/dist/public/assets/030-gaming-ufCRMN7S.js +1 -0
  103. package/dist/public/assets/030-granddaughter-DVCp3D8k.js +1 -0
  104. package/dist/public/assets/030-woman-8-Bv_tRQci.js +1 -0
  105. package/dist/public/assets/031-avatar-D0u5HVaC.js +1 -0
  106. package/dist/public/assets/031-grandpa-jKj5oB8I.js +1 -0
  107. package/dist/public/assets/031-superhero-DfSkK-j2.js +1 -0
  108. package/dist/public/assets/031-woman-7-DJHfCbTS.js +1 -0
  109. package/dist/public/assets/032-avatar-BvY6LKIZ.js +1 -0
  110. package/dist/public/assets/032-grandson-DIjRxDr-.js +1 -0
  111. package/dist/public/assets/032-man-6-CU7pJmmt.js +1 -0
  112. package/dist/public/assets/033-avatar-Dviobgw8.js +1 -0
  113. package/dist/public/assets/033-elf-CTAEJgfN.js +1 -0
  114. package/dist/public/assets/033-grandfather-BCXPgoJj.js +1 -0
  115. package/dist/public/assets/033-man-5-wgMylvNO.js +1 -0
  116. package/dist/public/assets/034-avatar-BqtUHT3_.js +1 -0
  117. package/dist/public/assets/034-little girl-CrgnV25d.js +1 -0
  118. package/dist/public/assets/034-man-4-DJdzfcSi.js +1 -0
  119. package/dist/public/assets/035-gaming-Bp8xnJp_.js +1 -0
  120. package/dist/public/assets/035-mother-Ccg5FDO8.js +1 -0
  121. package/dist/public/assets/036-avatar-q6pZKQVf.js +1 -0
  122. package/dist/public/assets/036-father-DzpzeKJJ.js +1 -0
  123. package/dist/public/assets/036-goblin-vDsj4aP0.js +1 -0
  124. package/dist/public/assets/036-grandmother-BI_Fl_aR.js +1 -0
  125. package/dist/public/assets/037-avatar-CmfvVc7v.js +1 -0
  126. package/dist/public/assets/037-grandfather-Dtp4XH-s.js +1 -0
  127. package/dist/public/assets/037-sister-BQv83Uhf.js +1 -0
  128. package/dist/public/assets/038-gaming-UtXFtv5k.js +1 -0
  129. package/dist/public/assets/038-girl-Cwg5Rv36.js +1 -0
  130. package/dist/public/assets/038-gnome-HbogTmVa.js +1 -0
  131. package/dist/public/assets/038-woman-6-B7jMwsP0.js +1 -0
  132. package/dist/public/assets/039-avatar-Bb3kVg4l.js +1 -0
  133. package/dist/public/assets/039-man-3-BSjLnoLV.js +1 -0
  134. package/dist/public/assets/039-student-CIi32WG9.js +1 -0
  135. package/dist/public/assets/040-aunt-B5XQH_sJ.js +1 -0
  136. package/dist/public/assets/040-gaming-CzTjib4v.js +1 -0
  137. package/dist/public/assets/040-vampire-UFzaHu5c.js +1 -0
  138. package/dist/public/assets/040-woman-5-Byal-gfX.js +1 -0
  139. package/dist/public/assets/041-avatar-CPQN2PvT.js +1 -0
  140. package/dist/public/assets/041-little boy-DUZFMrmJ.js +1 -0
  141. package/dist/public/assets/041-queen-CqFzW3uO.js +1 -0
  142. package/dist/public/assets/041-woman-4-CKi_Q-ns.js +1 -0
  143. package/dist/public/assets/042-avatar-BatY-WQG.js +1 -0
  144. package/dist/public/assets/042-cyclops-DAxxBVqG.js +1 -0
  145. package/dist/public/assets/042-man-omzAnpu1.js +1 -0
  146. package/dist/public/assets/042-woman-3-2Ki1Qz3j.js +1 -0
  147. package/dist/public/assets/043-avatar-DN026abg.js +1 -0
  148. package/dist/public/assets/043-child-D8_xXkcm.js +1 -0
  149. package/dist/public/assets/043-genie-DK78Ykl6.js +1 -0
  150. package/dist/public/assets/043-woman-2-DMnB0A-0.js +1 -0
  151. package/dist/public/assets/044-avatar-Bz2FAXUw.js +1 -0
  152. package/dist/public/assets/044-avatar-DzDIyuj0.js +1 -0
  153. package/dist/public/assets/044-fairy-BT73odE0.js +1 -0
  154. package/dist/public/assets/044-sister-CtNPPHh-.js +1 -0
  155. package/dist/public/assets/045-avatar-DgiFAlxj.js +1 -0
  156. package/dist/public/assets/045-man-2-BZPavI2b.js +1 -0
  157. package/dist/public/assets/045-young-B39gytpm.js +1 -0
  158. package/dist/public/assets/046-avatar-ClHeZPOV.js +1 -0
  159. package/dist/public/assets/046-brother-BSvJBKnA.js +1 -0
  160. package/dist/public/assets/046-witch-CVjM2-iJ.js +1 -0
  161. package/dist/public/assets/046-woman-1-CHWuzLfU.js +1 -0
  162. package/dist/public/assets/047-avatar-DM01i1ZC.js +1 -0
  163. package/dist/public/assets/047-king-knA4oWNa.js +1 -0
  164. package/dist/public/assets/047-man-1-DRWdGzL5.js +1 -0
  165. package/dist/public/assets/048-father-B0wiM2h6.js +1 -0
  166. package/dist/public/assets/048-gaming-D7s83-h3.js +1 -0
  167. package/dist/public/assets/048-girl-CxGcfLgU.js +1 -0
  168. package/dist/public/assets/049-avatar-BfGDVwlO.js +1 -0
  169. package/dist/public/assets/049-little boy-Bu5mmsUf.js +1 -0
  170. package/dist/public/assets/049-man-B3xcAso3.js +1 -0
  171. package/dist/public/assets/050-avatar-itJOA0dd.js +1 -0
  172. package/dist/public/assets/050-boy-DEIcVyYT.js +1 -0
  173. package/dist/public/assets/050-knight-KRUkfXDS.js +1 -0
  174. package/dist/public/assets/051-avatar-fISL-mLU.js +1 -0
  175. package/dist/public/assets/052-avatar-BYrM0aPD.js +1 -0
  176. package/dist/public/assets/053-avatar-B-rnufvm.js +1 -0
  177. package/dist/public/assets/054-avatar-B7rwS7Qv.js +1 -0
  178. package/dist/public/assets/055-gaming-DqUOmMvT.js +1 -0
  179. package/dist/public/assets/056-avatar-D1lb7KL9.js +1 -0
  180. package/dist/public/assets/057-avatar-Df7NRaJW.js +1 -0
  181. package/dist/public/assets/058-avatar-C8zso2zk.js +1 -0
  182. package/dist/public/assets/059-avatar-zEhHpOcr.js +1 -0
  183. package/dist/public/assets/060-avatar-DkNabW8M.js +1 -0
  184. package/dist/public/assets/index-CWvY7i3l.css +1 -0
  185. package/dist/public/assets/index-Zxr-JuKD.js +820 -0
  186. package/dist/public/index.html +14 -0
  187. package/dist/public/logo.svg +42 -0
  188. package/dist/server/src/dao/FridayAppMessage.js +103 -0
  189. package/dist/server/src/dao/InputRequest.js +99 -0
  190. package/dist/server/src/dao/Message.js +42 -0
  191. package/dist/server/src/dao/Reply.js +96 -0
  192. package/dist/server/src/dao/Run.js +395 -0
  193. package/dist/server/src/dao/Trace.js +643 -0
  194. package/dist/server/src/database.js +54 -0
  195. package/dist/server/src/index.js +211 -0
  196. package/dist/server/src/migrations/1730000000000-AddMessageReplyForeignKey.js +216 -0
  197. package/dist/server/src/migrations/1740000000000-MigrateSpanTable.js +638 -0
  198. package/dist/server/src/migrations/index.js +19 -0
  199. package/dist/server/src/models/FridayApp.js +69 -0
  200. package/dist/server/src/models/FridayAppView.js +94 -0
  201. package/dist/server/src/models/InputRequest.js +41 -0
  202. package/dist/server/src/models/Message.js +39 -0
  203. package/dist/server/src/models/ModelInvocationView.js +127 -0
  204. package/dist/server/src/models/Reply.js +50 -0
  205. package/dist/server/src/models/Run.js +63 -0
  206. package/dist/server/src/models/RunView.js +111 -0
  207. package/dist/server/src/models/Trace.js +154 -0
  208. package/dist/server/src/otel/grpc-server.js +154 -0
  209. package/dist/server/src/otel/opentelemetry/proto/collector/trace/v1/trace_service.js +309 -0
  210. package/dist/server/src/otel/opentelemetry/proto/common/v1/common.js +747 -0
  211. package/dist/server/src/otel/opentelemetry/proto/resource/v1/resource.js +170 -0
  212. package/dist/server/src/otel/opentelemetry/proto/trace/v1/trace.js +1134 -0
  213. package/dist/server/src/otel/processor.js +395 -0
  214. package/dist/server/src/otel/router.js +128 -0
  215. package/dist/server/src/services/ReplyingStateManager.js +21 -0
  216. package/dist/server/src/trpc/router.js +385 -0
  217. package/dist/server/src/trpc/socket.js +589 -0
  218. package/dist/server/src/utils/index.js +17 -0
  219. package/dist/server/src/utils/processUtils.js +27 -0
  220. package/dist/shared/src/config/client.js +6 -0
  221. package/dist/shared/src/config/common.js +32 -0
  222. package/dist/shared/src/config/friday.js +168 -0
  223. package/dist/shared/src/config/index.js +19 -0
  224. package/dist/shared/src/config/server.js +104 -0
  225. package/dist/shared/src/index.js +18 -0
  226. package/dist/shared/src/types/index.js +20 -0
  227. package/dist/shared/src/types/messageForm.js +25 -0
  228. package/dist/shared/src/types/trace.js +20 -0
  229. package/dist/shared/src/types/trpc.js +98 -0
  230. package/dist/shared/src/types/usage.js +7 -0
  231. package/dist/shared/src/utils/banner.js +74 -0
  232. package/dist/shared/src/utils/objectUtils.js +74 -0
  233. package/dist/shared/src/utils/terminal.js +30 -0
  234. package/dist/shared/src/utils/timeUtils.js +86 -0
  235. package/package.json +89 -0
@@ -0,0 +1,643 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.SpanDao = void 0;
13
+ const objectUtils_1 = require("../../../shared/src/utils/objectUtils");
14
+ const ModelInvocationView_1 = require("../models/ModelInvocationView");
15
+ const Trace_1 = require("../models/Trace");
16
+ class SpanDao {
17
+ static saveSpans(dataArray) {
18
+ return __awaiter(this, void 0, void 0, function* () {
19
+ try {
20
+ // Create SpanTable instances with embedded resource and scope data
21
+ const spans = dataArray.map((data) => {
22
+ // Extract key fields for indexing
23
+ const serviceName = this.extractServiceName(data.resource);
24
+ const operationName = this.extractOperationName(data.attributes);
25
+ const instrumentationName = this.extractInstrumentationName(data.scope);
26
+ const instrumentationVersion = this.extractInstrumentationVersion(data.scope);
27
+ const model = this.extractModel(data.attributes);
28
+ const inputTokens = this.extractInputTokens(data.attributes);
29
+ const outputTokens = this.extractOutputTokens(data.attributes);
30
+ const totalTokens = this.calculateTotalTokens(inputTokens, outputTokens);
31
+ const statusCode = data.status.code || 0;
32
+ const span = new Trace_1.SpanTable();
33
+ Object.assign(span, {
34
+ id: data.spanId, // Use spanId as the primary key
35
+ traceId: data.traceId,
36
+ spanId: data.spanId,
37
+ traceState: data.traceState,
38
+ parentSpanId: data.parentSpanId,
39
+ flags: data.flags,
40
+ name: data.name,
41
+ kind: data.kind, // Now it's a number (OpenTelemetry API enum)
42
+ startTimeUnixNano: data.startTimeUnixNano,
43
+ endTimeUnixNano: data.endTimeUnixNano,
44
+ attributes: data.attributes,
45
+ droppedAttributesCount: data.droppedAttributesCount,
46
+ events: data.events,
47
+ droppedEventsCount: data.droppedEventsCount,
48
+ links: data.links,
49
+ droppedLinksCount: data.droppedLinksCount,
50
+ status: data.status,
51
+ resource: data.resource,
52
+ scope: data.scope,
53
+ // Additional fields for our application
54
+ statusCode: statusCode,
55
+ serviceName: serviceName,
56
+ operationName: operationName,
57
+ instrumentationName: instrumentationName,
58
+ instrumentationVersion: instrumentationVersion,
59
+ model: model,
60
+ inputTokens: inputTokens,
61
+ outputTokens: outputTokens,
62
+ totalTokens: totalTokens,
63
+ conversationId: data.conversationId,
64
+ latencyNs: data.latencyNs,
65
+ });
66
+ return span;
67
+ });
68
+ // Save all spans in a single transaction
69
+ return yield Trace_1.SpanTable.save(spans);
70
+ }
71
+ catch (error) {
72
+ console.error('Error saving spans:', error);
73
+ throw error;
74
+ }
75
+ });
76
+ }
77
+ static getSpansByConversationId(conversationId) {
78
+ return __awaiter(this, void 0, void 0, function* () {
79
+ try {
80
+ const spans = yield Trace_1.SpanTable.find({
81
+ where: { conversationId },
82
+ order: { startTimeUnixNano: 'ASC' },
83
+ });
84
+ return spans.map((span) => ({
85
+ traceId: span.traceId,
86
+ spanId: span.spanId,
87
+ traceState: span.traceState,
88
+ parentSpanId: span.parentSpanId,
89
+ flags: span.flags,
90
+ name: span.name,
91
+ kind: span.kind,
92
+ startTimeUnixNano: span.startTimeUnixNano,
93
+ endTimeUnixNano: span.endTimeUnixNano,
94
+ attributes: span.attributes,
95
+ droppedAttributesCount: span.droppedAttributesCount || 0,
96
+ events: (span.events || []),
97
+ droppedEventsCount: span.droppedEventsCount || 0,
98
+ links: (span.links || []),
99
+ droppedLinksCount: span.droppedLinksCount || 0,
100
+ status: span.status,
101
+ resource: span.resource,
102
+ scope: span.scope,
103
+ conversationId: span.conversationId,
104
+ latencyNs: span.latencyNs,
105
+ }));
106
+ }
107
+ catch (error) {
108
+ console.error(`Error fetching spans for conversationId ${conversationId}:`, error);
109
+ throw error;
110
+ }
111
+ });
112
+ }
113
+ // Helper methods to extract key fields from nested data
114
+ static calculateTotalTokens(inputTokens, outputTokens) {
115
+ if (typeof inputTokens === 'number' &&
116
+ typeof outputTokens === 'number') {
117
+ return inputTokens + outputTokens;
118
+ }
119
+ if (typeof inputTokens === 'number') {
120
+ return inputTokens;
121
+ }
122
+ if (typeof outputTokens === 'number') {
123
+ return outputTokens;
124
+ }
125
+ return undefined;
126
+ }
127
+ static extractServiceName(resource) {
128
+ const value = (0, objectUtils_1.getNestedValue)(resource.attributes, 'service.name');
129
+ return typeof value === 'string' ? value : undefined;
130
+ }
131
+ static extractOperationName(attributes) {
132
+ const value = (0, objectUtils_1.getNestedValue)(attributes, 'gen_ai.operation.name');
133
+ return typeof value === 'string' ? value : undefined;
134
+ }
135
+ static extractInstrumentationName(scope) {
136
+ const value = (0, objectUtils_1.getNestedValue)(scope.attributes, 'server.name');
137
+ return typeof value === 'string' ? value : undefined;
138
+ }
139
+ static extractInstrumentationVersion(scope) {
140
+ const value = (0, objectUtils_1.getNestedValue)(scope.attributes, 'server.version');
141
+ return typeof value === 'string' ? value : undefined;
142
+ }
143
+ static extractModel(attributes) {
144
+ const value = (0, objectUtils_1.getNestedValue)(attributes, 'gen_ai.request.model');
145
+ return typeof value === 'string' ? value : undefined;
146
+ }
147
+ static extractInputTokens(attributes) {
148
+ const value = (0, objectUtils_1.getNestedValue)(attributes, 'gen_ai.usage.input_tokens');
149
+ return typeof value === 'number' ? value : undefined;
150
+ }
151
+ static extractOutputTokens(attributes) {
152
+ const value = (0, objectUtils_1.getNestedValue)(attributes, 'gen_ai.usage.output_tokens');
153
+ return typeof value === 'number' ? value : undefined;
154
+ }
155
+ // Trace listing and filtering methods
156
+ static getLatestTraces() {
157
+ return __awaiter(this, arguments, void 0, function* (limit = 10) {
158
+ return yield Trace_1.SpanTable.find({
159
+ order: { startTimeUnixNano: 'DESC' },
160
+ take: limit,
161
+ });
162
+ });
163
+ }
164
+ static getTracesByTraceId(traceId) {
165
+ return __awaiter(this, void 0, void 0, function* () {
166
+ return yield Trace_1.SpanTable.find({
167
+ where: { traceId },
168
+ order: { startTimeUnixNano: 'ASC' },
169
+ });
170
+ });
171
+ }
172
+ static getSpanById(spanId) {
173
+ return __awaiter(this, void 0, void 0, function* () {
174
+ return yield Trace_1.SpanTable.findOne({
175
+ where: { spanId },
176
+ });
177
+ });
178
+ }
179
+ static searchTraces(filters) {
180
+ return __awaiter(this, void 0, void 0, function* () {
181
+ const queryBuilder = Trace_1.SpanTable.createQueryBuilder('span');
182
+ if (filters.serviceName) {
183
+ queryBuilder.andWhere('span.serviceName = :serviceName', {
184
+ serviceName: filters.serviceName,
185
+ });
186
+ }
187
+ if (filters.operationName) {
188
+ queryBuilder.andWhere('span.operationName = :operationName', {
189
+ operationName: filters.operationName,
190
+ });
191
+ }
192
+ if (filters.instrumentationName) {
193
+ queryBuilder.andWhere('span.instrumentationName = :instrumentationName', { instrumentationName: filters.instrumentationName });
194
+ }
195
+ if (filters.model) {
196
+ queryBuilder.andWhere('span.model = :model', {
197
+ model: filters.model,
198
+ });
199
+ }
200
+ if (filters.status !== undefined) {
201
+ queryBuilder.andWhere('span.statusCode = :statusCode', {
202
+ statusCode: filters.status,
203
+ });
204
+ }
205
+ if (filters.startTime) {
206
+ queryBuilder.andWhere('span.startTimeUnixNano >= :startTime', {
207
+ startTime: filters.startTime,
208
+ });
209
+ }
210
+ if (filters.endTime) {
211
+ queryBuilder.andWhere('span.startTimeUnixNano <= :endTime', {
212
+ endTime: filters.endTime,
213
+ });
214
+ }
215
+ queryBuilder.orderBy('span.startTimeUnixNano', 'DESC');
216
+ if (filters.limit) {
217
+ queryBuilder.limit(filters.limit);
218
+ }
219
+ return yield queryBuilder.getMany();
220
+ });
221
+ }
222
+ static getModelInvocationViewData() {
223
+ return __awaiter(this, void 0, void 0, function* () {
224
+ const res = yield ModelInvocationView_1.ModelInvocationView.find();
225
+ if (res.length > 0) {
226
+ return res[0];
227
+ }
228
+ else {
229
+ throw new Error('ModelInvocationView data not found');
230
+ }
231
+ });
232
+ }
233
+ static getModelInvocationData(conversationId) {
234
+ return __awaiter(this, void 0, void 0, function* () {
235
+ // 1. Basic statistics
236
+ const basicStats = yield Trace_1.SpanTable.createQueryBuilder('span')
237
+ .select(`COUNT(CASE
238
+ WHEN (span.operationName = 'chat'
239
+ OR span.operationName = 'chat_model')
240
+ THEN 1
241
+ END)`, 'totalInvocations')
242
+ .addSelect(`COUNT(CASE
243
+ WHEN (span.operationName = 'chat'
244
+ OR span.operationName = 'chat_model')
245
+ AND span.totalTokens IS NOT NULL
246
+ THEN 1
247
+ END)`, 'chatInvocations')
248
+ .where('span.conversationId = :conversationId', { conversationId })
249
+ .getRawOne();
250
+ // 2. Chat token statistics (total and average)
251
+ const chatTokenStats = yield Trace_1.SpanTable.createQueryBuilder('span')
252
+ .select([
253
+ // Total - input tokens
254
+ `COALESCE(SUM(
255
+ CASE WHEN (span.operationName = 'chat'
256
+ OR span.operationName = 'chat_model')
257
+ AND span.totalTokens IS NOT NULL
258
+ THEN CAST(COALESCE(span.inputTokens, 0) AS INTEGER)
259
+ ELSE 0 END
260
+ ), 0) as totalPromptTokens`,
261
+ // Total - output tokens
262
+ `COALESCE(SUM(
263
+ CASE WHEN (span.operationName = 'chat'
264
+ OR span.operationName = 'chat_model')
265
+ AND span.totalTokens IS NOT NULL
266
+ THEN CAST(COALESCE(span.outputTokens, 0) AS INTEGER)
267
+ ELSE 0 END
268
+ ), 0) as totalCompletionTokens`,
269
+ // Total - total tokens
270
+ `COALESCE(SUM(
271
+ CASE WHEN (span.operationName = 'chat'
272
+ OR span.operationName = 'chat_model')
273
+ AND span.totalTokens IS NOT NULL
274
+ THEN CAST(COALESCE(span.totalTokens, 0) AS INTEGER)
275
+ ELSE 0 END
276
+ ), 0) as totalTokens`,
277
+ // Average - input tokens
278
+ `COALESCE(
279
+ CAST(SUM(
280
+ CASE WHEN (span.operationName = 'chat'
281
+ OR span.operationName = 'chat_model')
282
+ AND span.totalTokens IS NOT NULL
283
+ THEN CAST(COALESCE(span.inputTokens, 0) AS INTEGER)
284
+ ELSE 0 END
285
+ ) AS FLOAT) /
286
+ NULLIF(COUNT(CASE WHEN (span.operationName = 'chat'
287
+ OR span.operationName = 'chat_model')
288
+ AND span.totalTokens IS NOT NULL THEN 1 END), 0)
289
+ , 0) as avgPromptTokens`,
290
+ // Average - output tokens
291
+ `COALESCE(
292
+ CAST(SUM(
293
+ CASE WHEN (span.operationName = 'chat'
294
+ OR span.operationName = 'chat_model')
295
+ AND span.totalTokens IS NOT NULL
296
+ THEN CAST(COALESCE(span.outputTokens, 0) AS INTEGER)
297
+ ELSE 0 END
298
+ ) AS FLOAT) /
299
+ NULLIF(COUNT(CASE WHEN (span.operationName = 'chat'
300
+ OR span.operationName = 'chat_model')
301
+ AND span.totalTokens IS NOT NULL THEN 1 END), 0)
302
+ , 0) as avgCompletionTokens`,
303
+ // Average - total tokens
304
+ `COALESCE(
305
+ CAST(SUM(
306
+ CASE WHEN (span.operationName = 'chat'
307
+ OR span.operationName = 'chat_model')
308
+ AND span.totalTokens IS NOT NULL
309
+ THEN CAST(COALESCE(span.totalTokens, 0) AS INTEGER)
310
+ ELSE 0 END
311
+ ) AS FLOAT) /
312
+ NULLIF(COUNT(CASE WHEN (span.operationName = 'chat'
313
+ OR span.operationName = 'chat_model')
314
+ AND span.totalTokens IS NOT NULL THEN 1 END), 0)
315
+ , 0) as avgTotalTokens`,
316
+ ])
317
+ .where('span.conversationId = :conversationId', { conversationId })
318
+ .getRawOne();
319
+ // 3. Model invocation statistics (grouped by model)
320
+ const modelInvocations = yield Trace_1.SpanTable.createQueryBuilder('span')
321
+ .select(['span.model as modelName', 'COUNT(*) as invocations'])
322
+ .where('span.conversationId = :conversationId', { conversationId })
323
+ .andWhere("(span.operationName = 'chat' OR span.operationName = 'chat_model')")
324
+ .andWhere('span.totalTokens IS NOT NULL')
325
+ .groupBy('modelName')
326
+ .getRawMany();
327
+ // 4. Model token statistics (grouped by model)
328
+ const modelTokenStats = yield Trace_1.SpanTable.createQueryBuilder('span')
329
+ .select([
330
+ 'span.model as modelName',
331
+ // Total
332
+ `SUM(CAST(COALESCE(span.inputTokens, 0) AS INTEGER)) as totalPromptTokens`,
333
+ `SUM(CAST(COALESCE(span.outputTokens, 0) AS INTEGER)) as totalCompletionTokens`,
334
+ `SUM(CAST(COALESCE(span.totalTokens, 0) AS INTEGER)) as totalTokens`,
335
+ // Average
336
+ `CAST(SUM(CAST(COALESCE(span.inputTokens, 0) AS INTEGER)) AS FLOAT) / COUNT(*) as avgPromptTokens`,
337
+ `CAST(SUM(CAST(COALESCE(span.outputTokens, 0) AS INTEGER)) AS FLOAT) / COUNT(*) as avgCompletionTokens`,
338
+ `CAST(SUM(CAST(COALESCE(span.totalTokens, 0) AS INTEGER)) AS FLOAT) / COUNT(*) as avgTotalTokens`,
339
+ ])
340
+ .where('span.conversationId = :conversationId', { conversationId })
341
+ .andWhere("(span.operationName = 'chat' OR span.operationName = 'chat_model')")
342
+ .andWhere('span.totalTokens IS NOT NULL')
343
+ .groupBy('modelName')
344
+ .getRawMany();
345
+ // 5. Build return structure
346
+ return {
347
+ modelInvocations: Number(basicStats.totalInvocations),
348
+ chat: {
349
+ modelInvocations: Number(basicStats.chatInvocations),
350
+ totalTokens: {
351
+ promptTokens: Number(chatTokenStats.totalPromptTokens),
352
+ completionTokens: Number(chatTokenStats.totalCompletionTokens),
353
+ totalTokens: Number(chatTokenStats.totalTokens),
354
+ },
355
+ avgTokens: {
356
+ promptTokens: Number(chatTokenStats.avgPromptTokens),
357
+ completionTokens: Number(chatTokenStats.avgCompletionTokens),
358
+ totalTokens: Number(chatTokenStats.avgTotalTokens),
359
+ },
360
+ modelInvocationsByModel: modelInvocations.map((stat) => ({
361
+ modelName: stat.modelName || 'unknown',
362
+ invocations: Number(stat.invocations),
363
+ })),
364
+ totalTokensByModel: modelTokenStats.map((stat) => ({
365
+ modelName: stat.modelName || 'unknown',
366
+ promptTokens: Number(stat.totalPromptTokens),
367
+ completionTokens: Number(stat.totalCompletionTokens),
368
+ totalTokens: Number(stat.totalTokens),
369
+ })),
370
+ avgTokensByModel: modelTokenStats.map((stat) => ({
371
+ modelName: stat.modelName || 'unknown',
372
+ promptTokens: Number(stat.avgPromptTokens),
373
+ completionTokens: Number(stat.avgCompletionTokens),
374
+ totalTokens: Number(stat.avgTotalTokens),
375
+ })),
376
+ },
377
+ };
378
+ });
379
+ }
380
+ static deleteSpansByConversationIds(conversationIds) {
381
+ return __awaiter(this, void 0, void 0, function* () {
382
+ try {
383
+ if (conversationIds.length === 0) {
384
+ return 0;
385
+ }
386
+ const result = yield Trace_1.SpanTable.createQueryBuilder()
387
+ .delete()
388
+ .where('conversationId IN (:...conversationIds)', {
389
+ conversationIds,
390
+ })
391
+ .execute();
392
+ return result.affected || 0;
393
+ }
394
+ catch (error) {
395
+ console.error('Error deleting spans by conversationIds:', error);
396
+ throw error;
397
+ }
398
+ });
399
+ }
400
+ // Get unique trace IDs with aggregated information
401
+ static getTraceList(filters) {
402
+ return __awaiter(this, void 0, void 0, function* () {
403
+ try {
404
+ const queryBuilder = Trace_1.SpanTable.createQueryBuilder('span')
405
+ .select('span.traceId', 'traceId')
406
+ .addSelect('MIN(span.startTimeUnixNano)', 'startTime')
407
+ .addSelect('MAX(span.endTimeUnixNano)', 'endTime')
408
+ .addSelect('MIN(span.name)', 'name')
409
+ .addSelect('MAX(span.statusCode)', 'status')
410
+ .addSelect('COUNT(span.id)', 'spanCount')
411
+ .addSelect('SUM(COALESCE(span.totalTokens, 0))', 'totalTokens')
412
+ .groupBy('span.traceId');
413
+ if (filters.serviceName) {
414
+ queryBuilder.andWhere('span.serviceName = :serviceName', {
415
+ serviceName: filters.serviceName,
416
+ });
417
+ }
418
+ if (filters.operationName) {
419
+ queryBuilder.andWhere('span.operationName = :operationName', {
420
+ operationName: filters.operationName,
421
+ });
422
+ }
423
+ if (filters.status !== undefined) {
424
+ queryBuilder.andWhere('span.statusCode = :statusCode', {
425
+ statusCode: filters.status,
426
+ });
427
+ }
428
+ if (filters.startTime) {
429
+ queryBuilder.andWhere('span.startTimeUnixNano >= :startTime', {
430
+ startTime: filters.startTime,
431
+ });
432
+ }
433
+ if (filters.endTime) {
434
+ queryBuilder.andWhere('span.startTimeUnixNano <= :endTime', {
435
+ endTime: filters.endTime,
436
+ });
437
+ }
438
+ // Get total count (before pagination)
439
+ const countQuery = queryBuilder.clone();
440
+ const totalResult = yield countQuery.getRawMany();
441
+ const total = totalResult.length;
442
+ // Apply ordering and pagination
443
+ // Use the aggregate expression directly for ordering
444
+ queryBuilder.orderBy('MIN(span.startTimeUnixNano)', 'DESC');
445
+ if (filters.limit) {
446
+ queryBuilder.limit(filters.limit);
447
+ }
448
+ if (filters.offset) {
449
+ queryBuilder.offset(filters.offset);
450
+ }
451
+ const results = yield queryBuilder.getRawMany();
452
+ console.debug(`[TraceDao] getTraceList: found ${total} traces, returning ${results.length} with limit=${filters.limit}, offset=${filters.offset}`);
453
+ const traceIds = results.map((row) => row.traceId);
454
+ // Get root spans (spans with no parent or empty parent) for the traces in results
455
+ const rootSpans = traceIds.length > 0
456
+ ? yield Trace_1.SpanTable.createQueryBuilder('span')
457
+ .where('span.traceId IN (:...traceIds)', { traceIds })
458
+ .andWhere('(span.parentSpanId IS NULL OR span.parentSpanId = :emptyString)', { emptyString: '' })
459
+ .select(['span.traceId', 'span.name'])
460
+ .getMany()
461
+ : [];
462
+ const rootSpanMap = new Map(rootSpans.map((span) => [span.traceId, span]));
463
+ const traces = results.map((row) => {
464
+ try {
465
+ const startTimeNs = BigInt(row.startTime || '0');
466
+ const endTimeNs = BigInt(row.endTime || '0');
467
+ const duration = Number(endTimeNs - startTimeNs) / 1e9; // Convert nanoseconds to seconds
468
+ const rootSpan = rootSpanMap.get(row.traceId);
469
+ return {
470
+ traceId: row.traceId || '',
471
+ name: (rootSpan === null || rootSpan === void 0 ? void 0 : rootSpan.name) || row.name || 'Unknown',
472
+ startTime: row.startTime || '0',
473
+ endTime: row.endTime || '0',
474
+ duration,
475
+ status: Number(row.status) || 0,
476
+ spanCount: Number(row.spanCount) || 0,
477
+ totalTokens: row.totalTokens !== null &&
478
+ row.totalTokens !== undefined
479
+ ? Number(row.totalTokens)
480
+ : undefined,
481
+ };
482
+ }
483
+ catch (err) {
484
+ console.error('Error processing trace row:', row, err);
485
+ throw err;
486
+ }
487
+ });
488
+ console.debug(`[TraceDao] getTraceList: returning ${traces.length} traces`);
489
+ return { traces, total };
490
+ }
491
+ catch (error) {
492
+ console.error('Error getting trace list:', error);
493
+ throw error;
494
+ }
495
+ });
496
+ }
497
+ // Get a single trace with all spans
498
+ static getTrace(traceId) {
499
+ return __awaiter(this, void 0, void 0, function* () {
500
+ try {
501
+ const spans = yield this.getTracesByTraceId(traceId);
502
+ if (spans.length === 0) {
503
+ throw new Error(`Trace with id ${traceId} not found`);
504
+ }
505
+ // Calculate trace-level statistics
506
+ const startTimes = spans.map((s) => BigInt(s.startTimeUnixNano));
507
+ const endTimes = spans.map((s) => BigInt(s.endTimeUnixNano));
508
+ const minStartTime = startTimes.reduce((a, b) => (a < b ? a : b));
509
+ const maxEndTime = endTimes.reduce((a, b) => (a > b ? a : b));
510
+ const duration = Number(maxEndTime - minStartTime) / 1e9;
511
+ // Get status (ERROR if any span has error status)
512
+ const status = spans.some((s) => s.statusCode === 2) ? 2 : 1;
513
+ // Calculate total tokens
514
+ const totalTokens = spans.reduce((sum, s) => sum + (s.totalTokens || 0), 0);
515
+ const spanDataArray = spans.map((span) => ({
516
+ traceId: span.traceId,
517
+ spanId: span.spanId,
518
+ traceState: span.traceState,
519
+ parentSpanId: span.parentSpanId,
520
+ flags: span.flags,
521
+ name: span.name,
522
+ kind: span.kind,
523
+ startTimeUnixNano: span.startTimeUnixNano,
524
+ endTimeUnixNano: span.endTimeUnixNano,
525
+ attributes: span.attributes,
526
+ droppedAttributesCount: span.droppedAttributesCount || 0,
527
+ events: (span.events || []),
528
+ droppedEventsCount: span.droppedEventsCount || 0,
529
+ links: (span.links || []),
530
+ droppedLinksCount: span.droppedLinksCount || 0,
531
+ status: span.status,
532
+ resource: span.resource,
533
+ scope: span.scope,
534
+ conversationId: span.conversationId,
535
+ latencyNs: span.latencyNs,
536
+ }));
537
+ return {
538
+ traceId,
539
+ spans: spanDataArray,
540
+ startTime: minStartTime.toString(),
541
+ endTime: maxEndTime.toString(),
542
+ duration,
543
+ status,
544
+ totalTokens: totalTokens > 0 ? totalTokens : undefined,
545
+ };
546
+ }
547
+ catch (error) {
548
+ console.error(`Error getting trace ${traceId}:`, error);
549
+ throw error;
550
+ }
551
+ });
552
+ }
553
+ // Get trace statistics
554
+ static getTraceStatistic(filters) {
555
+ return __awaiter(this, void 0, void 0, function* () {
556
+ try {
557
+ const queryBuilder = Trace_1.SpanTable.createQueryBuilder('span');
558
+ if (filters === null || filters === void 0 ? void 0 : filters.serviceName) {
559
+ queryBuilder.andWhere('span.serviceName = :serviceName', {
560
+ serviceName: filters.serviceName,
561
+ });
562
+ }
563
+ if (filters === null || filters === void 0 ? void 0 : filters.operationName) {
564
+ queryBuilder.andWhere('span.operationName = :operationName', {
565
+ operationName: filters.operationName,
566
+ });
567
+ }
568
+ if (filters === null || filters === void 0 ? void 0 : filters.startTime) {
569
+ queryBuilder.andWhere('span.startTimeUnixNano >= :startTime', {
570
+ startTime: filters.startTime,
571
+ });
572
+ }
573
+ if (filters === null || filters === void 0 ? void 0 : filters.endTime) {
574
+ queryBuilder.andWhere('span.startTimeUnixNano <= :endTime', {
575
+ endTime: filters.endTime,
576
+ });
577
+ }
578
+ // Get total spans
579
+ const totalSpans = yield queryBuilder.getCount();
580
+ // Get unique trace count
581
+ const uniqueTracesQuery = queryBuilder
582
+ .clone()
583
+ .select('COUNT(DISTINCT span.traceId)', 'count')
584
+ .getRawOne();
585
+ const totalTraces = Number((yield uniqueTracesQuery).count || 0);
586
+ // Get error traces count
587
+ const errorTracesQuery = queryBuilder
588
+ .clone()
589
+ .select('COUNT(DISTINCT span.traceId)', 'count')
590
+ .andWhere('span.statusCode = :statusCode', { statusCode: 2 })
591
+ .getRawOne();
592
+ const errorTraces = Number((yield errorTracesQuery).count || 0);
593
+ // Get average duration
594
+ const durationQuery = yield queryBuilder
595
+ .clone()
596
+ .select('span.traceId', 'traceId')
597
+ .addSelect('MIN(span.startTimeUnixNano)', 'startTime')
598
+ .addSelect('MAX(span.endTimeUnixNano)', 'endTime')
599
+ .groupBy('span.traceId')
600
+ .getRawMany();
601
+ const durations = durationQuery.map((row) => {
602
+ const startTimeNs = BigInt(row.startTime);
603
+ const endTimeNs = BigInt(row.endTime);
604
+ return Number(endTimeNs - startTimeNs) / 1e9;
605
+ });
606
+ const avgDuration = durations.length > 0
607
+ ? durations.reduce((a, b) => a + b, 0) /
608
+ durations.length
609
+ : 0;
610
+ // Get total tokens
611
+ const tokensQuery = queryBuilder
612
+ .clone()
613
+ .select('SUM(COALESCE(span.totalTokens, 0))', 'total')
614
+ .getRawOne();
615
+ const totalTokens = Number((yield tokensQuery).total || 0);
616
+ // Get traces by status
617
+ const statusQuery = yield queryBuilder
618
+ .clone()
619
+ .select('span.statusCode', 'status')
620
+ .addSelect('COUNT(DISTINCT span.traceId)', 'count')
621
+ .groupBy('span.statusCode')
622
+ .getRawMany();
623
+ const tracesByStatus = statusQuery.map((row) => ({
624
+ status: Number(row.status) || 0,
625
+ count: Number(row.count) || 0,
626
+ }));
627
+ return {
628
+ totalTraces,
629
+ totalSpans,
630
+ errorTraces,
631
+ avgDuration,
632
+ totalTokens,
633
+ tracesByStatus,
634
+ };
635
+ }
636
+ catch (error) {
637
+ console.error('Error getting trace statistics:', error);
638
+ throw error;
639
+ }
640
+ });
641
+ }
642
+ }
643
+ exports.SpanDao = SpanDao;