@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.
- package/LICENSE +202 -0
- package/README.md +158 -0
- package/bin/cli.js +7 -0
- package/dist/app/friday/args.py +65 -0
- package/dist/app/friday/hook.py +52 -0
- package/dist/app/friday/main.py +164 -0
- package/dist/app/friday/model.py +124 -0
- package/dist/app/friday/tool/agentscope_tools.py +159 -0
- package/dist/app/friday/tool/utils.py +161 -0
- package/dist/app/friday/utils/common.py +28 -0
- package/dist/app/friday/utils/connect.py +63 -0
- package/dist/app/friday/utils/constants.py +8 -0
- package/dist/app/requirements.txt +1 -0
- package/dist/public/assets/001-aaron-Bb4ZO8rt.js +1 -0
- package/dist/public/assets/001-little girl-CnyQBZ0k.js +1 -0
- package/dist/public/assets/001-man-16-BO6NLPD_.js +1 -0
- package/dist/public/assets/002-avatar-C3FPnFjo.js +1 -0
- package/dist/public/assets/002-man-15-DfiiX2xR.js +1 -0
- package/dist/public/assets/002-old man-D4L-hA2l.js +1 -0
- package/dist/public/assets/003-avatar-UMXD80xE.js +1 -0
- package/dist/public/assets/003-cat-Cgyj1qJU.js +1 -0
- package/dist/public/assets/003-woman-20-Dy0WdjIG.js +1 -0
- package/dist/public/assets/004-avatar-D6Aw4tpO.js +1 -0
- package/dist/public/assets/004-dog-DUajs1ZO.js +1 -0
- package/dist/public/assets/004-woman-19-D5go5okE.js +1 -0
- package/dist/public/assets/005-avatar-NNQ3sWMe.js +1 -0
- package/dist/public/assets/005-child-SN-FoL0R.js +1 -0
- package/dist/public/assets/005-woman-18-AedSRg8a.js +1 -0
- package/dist/public/assets/006-avatar-FD8IUNL_.js +1 -0
- package/dist/public/assets/006-grandpa-T90IdpYr.js +1 -0
- package/dist/public/assets/006-man-14-DuMA-IZ-.js +1 -0
- package/dist/public/assets/007-avatar-eSQZtpkg.js +1 -0
- package/dist/public/assets/007-grandson-DV7UWhrR.js +1 -0
- package/dist/public/assets/007-man-13-owFTee2M.js +1 -0
- package/dist/public/assets/008-avatar-B9Rcm8D2.js +1 -0
- package/dist/public/assets/008-grandmother-1-BrQNVu9I.js +1 -0
- package/dist/public/assets/008-teenager-ClYxB7sG.js +1 -0
- package/dist/public/assets/009-avatar-DNSTEyOZ.js +1 -0
- package/dist/public/assets/009-grandfather-1-CPOn7LN0.js +1 -0
- package/dist/public/assets/009-grandmother-BAW_dEQC.js +1 -0
- package/dist/public/assets/010-avatar-CRXWH-A0.js +1 -0
- package/dist/public/assets/010-boy-1-C21LhAEr.js +1 -0
- package/dist/public/assets/011-woman-17-CI0UoPMR.js +1 -0
- package/dist/public/assets/012-avatar-BO5j-gGw.js +1 -0
- package/dist/public/assets/012-boy-T-hL8z9d.js +1 -0
- package/dist/public/assets/012-niece-M-tDMWMW.js +1 -0
- package/dist/public/assets/013-avatar-BTyOVKVo.js +1 -0
- package/dist/public/assets/013-granddaughter-D4VonRL-.js +1 -0
- package/dist/public/assets/013-woman-16-CuR7_ppw.js +1 -0
- package/dist/public/assets/014-avatar-DAW_Hvos.js +1 -0
- package/dist/public/assets/014-man-k8AXOF1Q.js +1 -0
- package/dist/public/assets/014-nurse-DnVigtmM.js +1 -0
- package/dist/public/assets/015-avatar-AxHR3j7h.js +1 -0
- package/dist/public/assets/015-woman-15-rDPwBxxc.js +1 -0
- package/dist/public/assets/015-woman-B71QRPrr.js +1 -0
- package/dist/public/assets/016-avatar-BVbMUisT.js +1 -0
- package/dist/public/assets/016-boy-BV_jzAu3.js +1 -0
- package/dist/public/assets/016-woman-14-D08zoPt9.js +1 -0
- package/dist/public/assets/017-gaming-BEpEpa1H.js +1 -0
- package/dist/public/assets/017-superpower-9xQAqiKN.js +1 -0
- package/dist/public/assets/017-uncle-EB1lmqAo.js +1 -0
- package/dist/public/assets/017-woman-13-BFsTAnGR.js +1 -0
- package/dist/public/assets/018-avatar-CnCLJXqW.js +1 -0
- package/dist/public/assets/018-young-QpIX6g3z.js +1 -0
- package/dist/public/assets/019-gaming-Dz5tR0Te.js +1 -0
- package/dist/public/assets/019-man-12-DiRb1dri.js +1 -0
- package/dist/public/assets/019-nephew-tXAgA9cr.js +1 -0
- package/dist/public/assets/020-avatar-Djtnu7jj.js +1 -0
- package/dist/public/assets/020-man-11-BNIZQyX4.js +1 -0
- package/dist/public/assets/020-young woman-BzklF8tq.js +1 -0
- package/dist/public/assets/021-aunt-CX9ikaTy.js +1 -0
- package/dist/public/assets/021-avatar-DP2sODK2.js +1 -0
- package/dist/public/assets/021-superhero-CIWREXp0.js +1 -0
- package/dist/public/assets/021-wizard-Dc9X50m_.js +1 -0
- package/dist/public/assets/021-woman-12-n9ipJK5z.js +1 -0
- package/dist/public/assets/022-father-B1_-ZTn1.js +1 -0
- package/dist/public/assets/022-woman-11-BUCsm06E.js +1 -0
- package/dist/public/assets/023-avatar-TeJ6vGqs.js +1 -0
- package/dist/public/assets/023-ghost-BYvGsa7H.js +1 -0
- package/dist/public/assets/023-man-10-Dfii-GE1.js +1 -0
- package/dist/public/assets/023-uncle-DoAMe1Iy.js +1 -0
- package/dist/public/assets/024-gaming-5ovd4aeT.js +1 -0
- package/dist/public/assets/024-man-9-CEenp_2W.js +1 -0
- package/dist/public/assets/024-prince-Fx3eCiNX.js +1 -0
- package/dist/public/assets/024-uncle-B6tqhqxU.js +1 -0
- package/dist/public/assets/025-gaming-CdlTp3Ub.js +1 -0
- package/dist/public/assets/025-man-8-Cfp6jNt4.js +1 -0
- package/dist/public/assets/025-man-BxhR-XTO.js +1 -0
- package/dist/public/assets/025-princess-Di5TdSnG.js +1 -0
- package/dist/public/assets/026-avatar-DojOPRVd.js +1 -0
- package/dist/public/assets/026-dad-CHaoMWM5.js +1 -0
- package/dist/public/assets/026-owl-Dl-UtZM8.js +1 -0
- package/dist/public/assets/026-woman-10-CywXJiaj.js +1 -0
- package/dist/public/assets/027-avatar-CrEyLmOb.js +1 -0
- package/dist/public/assets/027-girl-Box_GaMO.js +1 -0
- package/dist/public/assets/028-gaming-CmOZ2uGp.js +1 -0
- package/dist/public/assets/028-mom-tEacX7K4.js +1 -0
- package/dist/public/assets/028-woman-9-C1oq4sFk.js +1 -0
- package/dist/public/assets/029-boy-CVg6oMuZ.js +1 -0
- package/dist/public/assets/029-man-7-C4eeEeTQ.js +1 -0
- package/dist/public/assets/030-elf-C8vikAvx.js +1 -0
- package/dist/public/assets/030-gaming-ufCRMN7S.js +1 -0
- package/dist/public/assets/030-granddaughter-DVCp3D8k.js +1 -0
- package/dist/public/assets/030-woman-8-Bv_tRQci.js +1 -0
- package/dist/public/assets/031-avatar-D0u5HVaC.js +1 -0
- package/dist/public/assets/031-grandpa-jKj5oB8I.js +1 -0
- package/dist/public/assets/031-superhero-DfSkK-j2.js +1 -0
- package/dist/public/assets/031-woman-7-DJHfCbTS.js +1 -0
- package/dist/public/assets/032-avatar-BvY6LKIZ.js +1 -0
- package/dist/public/assets/032-grandson-DIjRxDr-.js +1 -0
- package/dist/public/assets/032-man-6-CU7pJmmt.js +1 -0
- package/dist/public/assets/033-avatar-Dviobgw8.js +1 -0
- package/dist/public/assets/033-elf-CTAEJgfN.js +1 -0
- package/dist/public/assets/033-grandfather-BCXPgoJj.js +1 -0
- package/dist/public/assets/033-man-5-wgMylvNO.js +1 -0
- package/dist/public/assets/034-avatar-BqtUHT3_.js +1 -0
- package/dist/public/assets/034-little girl-CrgnV25d.js +1 -0
- package/dist/public/assets/034-man-4-DJdzfcSi.js +1 -0
- package/dist/public/assets/035-gaming-Bp8xnJp_.js +1 -0
- package/dist/public/assets/035-mother-Ccg5FDO8.js +1 -0
- package/dist/public/assets/036-avatar-q6pZKQVf.js +1 -0
- package/dist/public/assets/036-father-DzpzeKJJ.js +1 -0
- package/dist/public/assets/036-goblin-vDsj4aP0.js +1 -0
- package/dist/public/assets/036-grandmother-BI_Fl_aR.js +1 -0
- package/dist/public/assets/037-avatar-CmfvVc7v.js +1 -0
- package/dist/public/assets/037-grandfather-Dtp4XH-s.js +1 -0
- package/dist/public/assets/037-sister-BQv83Uhf.js +1 -0
- package/dist/public/assets/038-gaming-UtXFtv5k.js +1 -0
- package/dist/public/assets/038-girl-Cwg5Rv36.js +1 -0
- package/dist/public/assets/038-gnome-HbogTmVa.js +1 -0
- package/dist/public/assets/038-woman-6-B7jMwsP0.js +1 -0
- package/dist/public/assets/039-avatar-Bb3kVg4l.js +1 -0
- package/dist/public/assets/039-man-3-BSjLnoLV.js +1 -0
- package/dist/public/assets/039-student-CIi32WG9.js +1 -0
- package/dist/public/assets/040-aunt-B5XQH_sJ.js +1 -0
- package/dist/public/assets/040-gaming-CzTjib4v.js +1 -0
- package/dist/public/assets/040-vampire-UFzaHu5c.js +1 -0
- package/dist/public/assets/040-woman-5-Byal-gfX.js +1 -0
- package/dist/public/assets/041-avatar-CPQN2PvT.js +1 -0
- package/dist/public/assets/041-little boy-DUZFMrmJ.js +1 -0
- package/dist/public/assets/041-queen-CqFzW3uO.js +1 -0
- package/dist/public/assets/041-woman-4-CKi_Q-ns.js +1 -0
- package/dist/public/assets/042-avatar-BatY-WQG.js +1 -0
- package/dist/public/assets/042-cyclops-DAxxBVqG.js +1 -0
- package/dist/public/assets/042-man-omzAnpu1.js +1 -0
- package/dist/public/assets/042-woman-3-2Ki1Qz3j.js +1 -0
- package/dist/public/assets/043-avatar-DN026abg.js +1 -0
- package/dist/public/assets/043-child-D8_xXkcm.js +1 -0
- package/dist/public/assets/043-genie-DK78Ykl6.js +1 -0
- package/dist/public/assets/043-woman-2-DMnB0A-0.js +1 -0
- package/dist/public/assets/044-avatar-Bz2FAXUw.js +1 -0
- package/dist/public/assets/044-avatar-DzDIyuj0.js +1 -0
- package/dist/public/assets/044-fairy-BT73odE0.js +1 -0
- package/dist/public/assets/044-sister-CtNPPHh-.js +1 -0
- package/dist/public/assets/045-avatar-DgiFAlxj.js +1 -0
- package/dist/public/assets/045-man-2-BZPavI2b.js +1 -0
- package/dist/public/assets/045-young-B39gytpm.js +1 -0
- package/dist/public/assets/046-avatar-ClHeZPOV.js +1 -0
- package/dist/public/assets/046-brother-BSvJBKnA.js +1 -0
- package/dist/public/assets/046-witch-CVjM2-iJ.js +1 -0
- package/dist/public/assets/046-woman-1-CHWuzLfU.js +1 -0
- package/dist/public/assets/047-avatar-DM01i1ZC.js +1 -0
- package/dist/public/assets/047-king-knA4oWNa.js +1 -0
- package/dist/public/assets/047-man-1-DRWdGzL5.js +1 -0
- package/dist/public/assets/048-father-B0wiM2h6.js +1 -0
- package/dist/public/assets/048-gaming-D7s83-h3.js +1 -0
- package/dist/public/assets/048-girl-CxGcfLgU.js +1 -0
- package/dist/public/assets/049-avatar-BfGDVwlO.js +1 -0
- package/dist/public/assets/049-little boy-Bu5mmsUf.js +1 -0
- package/dist/public/assets/049-man-B3xcAso3.js +1 -0
- package/dist/public/assets/050-avatar-itJOA0dd.js +1 -0
- package/dist/public/assets/050-boy-DEIcVyYT.js +1 -0
- package/dist/public/assets/050-knight-KRUkfXDS.js +1 -0
- package/dist/public/assets/051-avatar-fISL-mLU.js +1 -0
- package/dist/public/assets/052-avatar-BYrM0aPD.js +1 -0
- package/dist/public/assets/053-avatar-B-rnufvm.js +1 -0
- package/dist/public/assets/054-avatar-B7rwS7Qv.js +1 -0
- package/dist/public/assets/055-gaming-DqUOmMvT.js +1 -0
- package/dist/public/assets/056-avatar-D1lb7KL9.js +1 -0
- package/dist/public/assets/057-avatar-Df7NRaJW.js +1 -0
- package/dist/public/assets/058-avatar-C8zso2zk.js +1 -0
- package/dist/public/assets/059-avatar-zEhHpOcr.js +1 -0
- package/dist/public/assets/060-avatar-DkNabW8M.js +1 -0
- package/dist/public/assets/index-CWvY7i3l.css +1 -0
- package/dist/public/assets/index-Zxr-JuKD.js +820 -0
- package/dist/public/index.html +14 -0
- package/dist/public/logo.svg +42 -0
- package/dist/server/src/dao/FridayAppMessage.js +103 -0
- package/dist/server/src/dao/InputRequest.js +99 -0
- package/dist/server/src/dao/Message.js +42 -0
- package/dist/server/src/dao/Reply.js +96 -0
- package/dist/server/src/dao/Run.js +395 -0
- package/dist/server/src/dao/Trace.js +643 -0
- package/dist/server/src/database.js +54 -0
- package/dist/server/src/index.js +211 -0
- package/dist/server/src/migrations/1730000000000-AddMessageReplyForeignKey.js +216 -0
- package/dist/server/src/migrations/1740000000000-MigrateSpanTable.js +638 -0
- package/dist/server/src/migrations/index.js +19 -0
- package/dist/server/src/models/FridayApp.js +69 -0
- package/dist/server/src/models/FridayAppView.js +94 -0
- package/dist/server/src/models/InputRequest.js +41 -0
- package/dist/server/src/models/Message.js +39 -0
- package/dist/server/src/models/ModelInvocationView.js +127 -0
- package/dist/server/src/models/Reply.js +50 -0
- package/dist/server/src/models/Run.js +63 -0
- package/dist/server/src/models/RunView.js +111 -0
- package/dist/server/src/models/Trace.js +154 -0
- package/dist/server/src/otel/grpc-server.js +154 -0
- package/dist/server/src/otel/opentelemetry/proto/collector/trace/v1/trace_service.js +309 -0
- package/dist/server/src/otel/opentelemetry/proto/common/v1/common.js +747 -0
- package/dist/server/src/otel/opentelemetry/proto/resource/v1/resource.js +170 -0
- package/dist/server/src/otel/opentelemetry/proto/trace/v1/trace.js +1134 -0
- package/dist/server/src/otel/processor.js +395 -0
- package/dist/server/src/otel/router.js +128 -0
- package/dist/server/src/services/ReplyingStateManager.js +21 -0
- package/dist/server/src/trpc/router.js +385 -0
- package/dist/server/src/trpc/socket.js +589 -0
- package/dist/server/src/utils/index.js +17 -0
- package/dist/server/src/utils/processUtils.js +27 -0
- package/dist/shared/src/config/client.js +6 -0
- package/dist/shared/src/config/common.js +32 -0
- package/dist/shared/src/config/friday.js +168 -0
- package/dist/shared/src/config/index.js +19 -0
- package/dist/shared/src/config/server.js +104 -0
- package/dist/shared/src/index.js +18 -0
- package/dist/shared/src/types/index.js +20 -0
- package/dist/shared/src/types/messageForm.js +25 -0
- package/dist/shared/src/types/trace.js +20 -0
- package/dist/shared/src/types/trpc.js +98 -0
- package/dist/shared/src/types/usage.js +7 -0
- package/dist/shared/src/utils/banner.js +74 -0
- package/dist/shared/src/utils/objectUtils.js +74 -0
- package/dist/shared/src/utils/terminal.js +30 -0
- package/dist/shared/src/utils/timeUtils.js +86 -0
- package/package.json +89 -0
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SpanProcessor = void 0;
|
|
4
|
+
const trace_1 = require("../../../shared/src/types/trace");
|
|
5
|
+
const objectUtils_1 = require("../../../shared/src/utils/objectUtils");
|
|
6
|
+
const timeUtils_1 = require("../../../shared/src/utils/timeUtils");
|
|
7
|
+
class SpanProcessor {
|
|
8
|
+
static validateOTLPSpan(span) {
|
|
9
|
+
try {
|
|
10
|
+
const spanObj = span;
|
|
11
|
+
if (!spanObj.trace_id || !spanObj.span_id || !spanObj.name) {
|
|
12
|
+
console.error('[SpanProcessor] Missing required span fields');
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
if (!spanObj.start_time_unix_nano || !spanObj.end_time_unix_nano) {
|
|
16
|
+
console.error('[SpanProcessor] Missing span time fields');
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
if (isNaN(Number(spanObj.start_time_unix_nano)) ||
|
|
20
|
+
isNaN(Number(spanObj.end_time_unix_nano))) {
|
|
21
|
+
console.error('[SpanProcessor] Invalid timestamp format');
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
console.error('[SpanProcessor] Validation error:', error);
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
static decodeOTLPSpan(span, resource, scope) {
|
|
32
|
+
const spanObj = span;
|
|
33
|
+
const traceId = this.decodeIdentifier(spanObj.trace_id);
|
|
34
|
+
const spanId = this.decodeIdentifier(spanObj.span_id);
|
|
35
|
+
const parentId = spanObj.parent_span_id
|
|
36
|
+
? this.decodeIdentifier(spanObj.parent_span_id)
|
|
37
|
+
: undefined;
|
|
38
|
+
const startTimeUnixNano = (0, timeUtils_1.decodeUnixNano)(spanObj.start_time_unix_nano);
|
|
39
|
+
const endTimeUnixNano = (0, timeUtils_1.decodeUnixNano)(spanObj.end_time_unix_nano);
|
|
40
|
+
// Decode attributes
|
|
41
|
+
let attributes = this.decodeAttributes(spanObj.attributes);
|
|
42
|
+
let spanName = typeof spanObj.name === 'string' ? spanObj.name : '';
|
|
43
|
+
if (scope.name.toLowerCase().includes('agentscope.tracing._trace')) {
|
|
44
|
+
this.logOldProtocolWarning();
|
|
45
|
+
const newValues = this.convertOldProtocolToNew(attributes, {
|
|
46
|
+
name: spanName,
|
|
47
|
+
});
|
|
48
|
+
spanName = newValues.span_name;
|
|
49
|
+
attributes = newValues.attributes;
|
|
50
|
+
}
|
|
51
|
+
const events = this.decodeArray(spanObj.events, (e) => this.decodeEvent(e));
|
|
52
|
+
const links = this.decodeArray(spanObj.links, (l) => this.decodeLink(l));
|
|
53
|
+
const status = this.decodeStatus(spanObj.status);
|
|
54
|
+
return {
|
|
55
|
+
traceId: traceId,
|
|
56
|
+
spanId: spanId,
|
|
57
|
+
traceState: typeof spanObj.trace_state === 'string'
|
|
58
|
+
? spanObj.trace_state
|
|
59
|
+
: undefined,
|
|
60
|
+
parentSpanId: parentId,
|
|
61
|
+
flags: typeof spanObj.flags === 'number' ? spanObj.flags : undefined,
|
|
62
|
+
name: spanName,
|
|
63
|
+
kind: typeof spanObj.kind === 'number' ? spanObj.kind : 0,
|
|
64
|
+
startTimeUnixNano: startTimeUnixNano,
|
|
65
|
+
endTimeUnixNano: endTimeUnixNano,
|
|
66
|
+
attributes: attributes,
|
|
67
|
+
droppedAttributesCount: typeof spanObj.dropped_attributes_count === 'number'
|
|
68
|
+
? spanObj.dropped_attributes_count
|
|
69
|
+
: 0,
|
|
70
|
+
events: events,
|
|
71
|
+
droppedEventsCount: typeof spanObj.dropped_events_count === 'number'
|
|
72
|
+
? spanObj.dropped_events_count
|
|
73
|
+
: 0,
|
|
74
|
+
links: links,
|
|
75
|
+
droppedLinksCount: typeof spanObj.dropped_links_count === 'number'
|
|
76
|
+
? spanObj.dropped_links_count
|
|
77
|
+
: 0,
|
|
78
|
+
status: status,
|
|
79
|
+
resource: resource,
|
|
80
|
+
scope: scope,
|
|
81
|
+
conversationId: this.getConversationId(attributes),
|
|
82
|
+
latencyNs: (0, timeUtils_1.getTimeDifferenceNano)(startTimeUnixNano, endTimeUnixNano),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
static decodeAttributes(attributes) {
|
|
86
|
+
const attrs = Array.isArray(attributes) ? attributes : [];
|
|
87
|
+
return this.unflattenAttributes(this.loadJsonStrings(this.decodeKeyValues(attrs)));
|
|
88
|
+
}
|
|
89
|
+
static decodeArray(value, mapper) {
|
|
90
|
+
return Array.isArray(value) ? value.map(mapper) : [];
|
|
91
|
+
}
|
|
92
|
+
static getConversationId(attributes) {
|
|
93
|
+
const conversationId = (0, objectUtils_1.getNestedValue)(attributes, 'gen_ai.conversation.id');
|
|
94
|
+
if (conversationId)
|
|
95
|
+
return String(conversationId);
|
|
96
|
+
const oldRunId = (0, objectUtils_1.getNestedValue)(attributes, 'project.run_id');
|
|
97
|
+
return oldRunId ? String(oldRunId) : 'unknown';
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Log warning about old protocol format.
|
|
101
|
+
* - Within 5 minutes: warn on each detection
|
|
102
|
+
* - After 5 minutes: stop warning
|
|
103
|
+
*/
|
|
104
|
+
static logOldProtocolWarning() {
|
|
105
|
+
const now = Date.now();
|
|
106
|
+
const timeSinceStart = now - this.warningPeriodStartTime;
|
|
107
|
+
if (timeSinceStart < this.WARNING_PERIOD_MS) {
|
|
108
|
+
console.warn('[Warning] Agentscope SDK version is too low. Please update to 1.0.9 or higher.');
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Convert old protocol format attributes to new format
|
|
113
|
+
*
|
|
114
|
+
* Old format -> New format mappings:
|
|
115
|
+
* - project.run_id -> gen_ai.conversation.id
|
|
116
|
+
* - output.usage.* -> gen_ai.usage.*
|
|
117
|
+
* - output.model -> gen_ai.request.model
|
|
118
|
+
* - output.response.* -> gen_ai.response.*
|
|
119
|
+
*
|
|
120
|
+
* @param attributes The attributes object to convert
|
|
121
|
+
* @param span The original span object (for additional context if needed)
|
|
122
|
+
* @returns Converted attributes in new format
|
|
123
|
+
*/
|
|
124
|
+
static convertOldProtocolToNew(attributes, span) {
|
|
125
|
+
if (!attributes || typeof attributes !== 'object') {
|
|
126
|
+
return { span_name: span.name || '', attributes: attributes || {} };
|
|
127
|
+
}
|
|
128
|
+
// Check if already in new format by looking for gen_ai attributes
|
|
129
|
+
if ((0, objectUtils_1.getNestedValue)(attributes, 'gen_ai')) {
|
|
130
|
+
return { span_name: span.name || '', attributes: attributes };
|
|
131
|
+
}
|
|
132
|
+
const newAttributes = {
|
|
133
|
+
gen_ai: {
|
|
134
|
+
conversation: {},
|
|
135
|
+
request: {},
|
|
136
|
+
operation: {},
|
|
137
|
+
agent: {},
|
|
138
|
+
tool: {},
|
|
139
|
+
},
|
|
140
|
+
agentscope: {
|
|
141
|
+
function: {
|
|
142
|
+
input: {},
|
|
143
|
+
output: {},
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
const genAi = newAttributes.gen_ai;
|
|
148
|
+
const conversation = genAi.conversation;
|
|
149
|
+
const operation = genAi.operation;
|
|
150
|
+
const agentscope = newAttributes.agentscope;
|
|
151
|
+
const request = genAi.request;
|
|
152
|
+
const agent = genAi.agent;
|
|
153
|
+
const tool = genAi.tool;
|
|
154
|
+
const agentscopeFunction = agentscope.function;
|
|
155
|
+
agentscopeFunction.name = span.name;
|
|
156
|
+
conversation.id = (0, objectUtils_1.getNestedValue)(attributes, 'project.run_id');
|
|
157
|
+
const span_kind = (0, objectUtils_1.getNestedValue)(attributes, 'span.kind');
|
|
158
|
+
// Copy input, metadata, output
|
|
159
|
+
const inputValue = (0, objectUtils_1.getNestedValue)(attributes, 'input');
|
|
160
|
+
if (inputValue)
|
|
161
|
+
agentscopeFunction.input = inputValue;
|
|
162
|
+
const metadataValue = (0, objectUtils_1.getNestedValue)(attributes, 'metadata');
|
|
163
|
+
const outputValue = (0, objectUtils_1.getNestedValue)(attributes, 'output');
|
|
164
|
+
if (outputValue) {
|
|
165
|
+
agentscopeFunction.output = outputValue;
|
|
166
|
+
if (outputValue.usage && typeof outputValue.usage === 'object') {
|
|
167
|
+
if (!genAi.usage) {
|
|
168
|
+
genAi.usage = {};
|
|
169
|
+
}
|
|
170
|
+
const usage = genAi.usage;
|
|
171
|
+
usage.input_tokens = outputValue.usage.input_tokens;
|
|
172
|
+
usage.output_tokens = outputValue.usage.output_tokens;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
let span_name = span.name || '';
|
|
176
|
+
const metadataObj = metadataValue;
|
|
177
|
+
if (span_kind === trace_1.OldSpanKind.AGENT) {
|
|
178
|
+
operation.name = 'invoke_agent';
|
|
179
|
+
span_name =
|
|
180
|
+
operation.name + ' ' + ((metadataObj === null || metadataObj === void 0 ? void 0 : metadataObj.name) || '');
|
|
181
|
+
agent.name = (metadataObj === null || metadataObj === void 0 ? void 0 : metadataObj.name) || '';
|
|
182
|
+
}
|
|
183
|
+
else if (span_kind === trace_1.OldSpanKind.TOOL) {
|
|
184
|
+
operation.name = 'execute_tool';
|
|
185
|
+
span_name =
|
|
186
|
+
operation.name + ' ' + ((metadataObj === null || metadataObj === void 0 ? void 0 : metadataObj.name) || '');
|
|
187
|
+
tool.name = (metadataObj === null || metadataObj === void 0 ? void 0 : metadataObj.name) || '';
|
|
188
|
+
}
|
|
189
|
+
else if (span_kind === trace_1.OldSpanKind.LLM) {
|
|
190
|
+
operation.name = 'chat';
|
|
191
|
+
span_name =
|
|
192
|
+
operation.name +
|
|
193
|
+
' ' +
|
|
194
|
+
((metadataObj === null || metadataObj === void 0 ? void 0 : metadataObj.model_name) || '');
|
|
195
|
+
request.model = (metadataObj === null || metadataObj === void 0 ? void 0 : metadataObj.model_name) || '';
|
|
196
|
+
}
|
|
197
|
+
else if (span_kind === trace_1.OldSpanKind.EMBEDDING) {
|
|
198
|
+
operation.name = 'embeddings';
|
|
199
|
+
span_name =
|
|
200
|
+
operation.name +
|
|
201
|
+
' ' +
|
|
202
|
+
((metadataObj === null || metadataObj === void 0 ? void 0 : metadataObj.model_name) || '');
|
|
203
|
+
request.model = (metadataObj === null || metadataObj === void 0 ? void 0 : metadataObj.model_name) || '';
|
|
204
|
+
}
|
|
205
|
+
else if (span_kind === trace_1.OldSpanKind.FORMATTER) {
|
|
206
|
+
operation.name = 'format';
|
|
207
|
+
span_name =
|
|
208
|
+
operation.name + ' ' + ((metadataObj === null || metadataObj === void 0 ? void 0 : metadataObj.name) || '');
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
operation.name = 'unknown';
|
|
212
|
+
}
|
|
213
|
+
return { span_name, attributes: newAttributes };
|
|
214
|
+
}
|
|
215
|
+
static decodeIdentifier(identifier) {
|
|
216
|
+
if (!identifier)
|
|
217
|
+
return '';
|
|
218
|
+
if (typeof identifier === 'string')
|
|
219
|
+
return identifier;
|
|
220
|
+
if (identifier instanceof Uint8Array) {
|
|
221
|
+
return Buffer.from(identifier).toString('hex');
|
|
222
|
+
}
|
|
223
|
+
return '';
|
|
224
|
+
}
|
|
225
|
+
static decodeKeyValues(keyValues) {
|
|
226
|
+
const result = {};
|
|
227
|
+
for (const kv of keyValues) {
|
|
228
|
+
const kvObj = kv;
|
|
229
|
+
if (kvObj.key && kvObj.value) {
|
|
230
|
+
result[String(kvObj.key)] = this.decodeAnyValue(kvObj.value);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return result;
|
|
234
|
+
}
|
|
235
|
+
static decodeAnyValue(value) {
|
|
236
|
+
const valueObj = value;
|
|
237
|
+
if (valueObj.bool_value !== false && valueObj.bool_value !== undefined)
|
|
238
|
+
return valueObj.bool_value;
|
|
239
|
+
if (valueObj.int_value !== 0 && valueObj.int_value !== undefined)
|
|
240
|
+
return valueObj.int_value;
|
|
241
|
+
if (valueObj.double_value !== 0 && valueObj.double_value !== undefined)
|
|
242
|
+
return valueObj.double_value;
|
|
243
|
+
if (valueObj.string_value !== '' && valueObj.string_value !== undefined)
|
|
244
|
+
return valueObj.string_value;
|
|
245
|
+
const arrayValue = valueObj.array_value;
|
|
246
|
+
if (arrayValue === null || arrayValue === void 0 ? void 0 : arrayValue.values) {
|
|
247
|
+
return arrayValue.values.map((v) => this.decodeAnyValue(v));
|
|
248
|
+
}
|
|
249
|
+
const kvlistValue = valueObj.kvlist_value;
|
|
250
|
+
if (kvlistValue === null || kvlistValue === void 0 ? void 0 : kvlistValue.values) {
|
|
251
|
+
return this.decodeKeyValues(kvlistValue.values);
|
|
252
|
+
}
|
|
253
|
+
if (valueObj.bytes_value &&
|
|
254
|
+
typeof valueObj.bytes_value === 'object' &&
|
|
255
|
+
Object.keys(valueObj.bytes_value).length > 0) {
|
|
256
|
+
return valueObj.bytes_value;
|
|
257
|
+
}
|
|
258
|
+
if (valueObj.int_value !== undefined)
|
|
259
|
+
return valueObj.int_value;
|
|
260
|
+
if (valueObj.double_value !== undefined)
|
|
261
|
+
return valueObj.double_value;
|
|
262
|
+
if (valueObj.string_value !== undefined)
|
|
263
|
+
return valueObj.string_value;
|
|
264
|
+
if (valueObj.bool_value !== undefined)
|
|
265
|
+
return valueObj.bool_value;
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
static decodeStatus(status) {
|
|
269
|
+
if (!status || typeof status !== 'object') {
|
|
270
|
+
return { code: 0, message: '' }; // UNSET
|
|
271
|
+
}
|
|
272
|
+
const s = status;
|
|
273
|
+
return {
|
|
274
|
+
code: typeof s.code === 'number' ? s.code : 0,
|
|
275
|
+
message: typeof s.message === 'string' ? s.message : '',
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
static decodeEvent(event) {
|
|
279
|
+
const e = event;
|
|
280
|
+
return {
|
|
281
|
+
name: typeof e.name === 'string' ? e.name : '',
|
|
282
|
+
time: (0, timeUtils_1.decodeUnixNano)(e.time_unix_nano),
|
|
283
|
+
attributes: this.decodeAttributes(e.attributes),
|
|
284
|
+
droppedAttributesCount: typeof e.dropped_attributes_count === 'number'
|
|
285
|
+
? e.dropped_attributes_count
|
|
286
|
+
: 0,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
static decodeLink(link) {
|
|
290
|
+
const l = link;
|
|
291
|
+
return {
|
|
292
|
+
traceId: this.decodeIdentifier(l.trace_id),
|
|
293
|
+
spanId: this.decodeIdentifier(l.span_id),
|
|
294
|
+
traceState: typeof l.trace_state === 'string' ? l.trace_state : undefined,
|
|
295
|
+
flags: typeof l.flags === 'number' ? l.flags : undefined,
|
|
296
|
+
attributes: this.decodeAttributes(l.attributes),
|
|
297
|
+
droppedAttributesCount: typeof l.dropped_attributes_count === 'number'
|
|
298
|
+
? l.dropped_attributes_count
|
|
299
|
+
: 0,
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
static unflattenAttributes(flat) {
|
|
303
|
+
return (0, objectUtils_1.unflattenObject)(flat);
|
|
304
|
+
}
|
|
305
|
+
static loadJsonStrings(attributes) {
|
|
306
|
+
const result = {};
|
|
307
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
308
|
+
if (typeof value === 'string') {
|
|
309
|
+
try {
|
|
310
|
+
result[key] = JSON.parse(value);
|
|
311
|
+
}
|
|
312
|
+
catch (_a) {
|
|
313
|
+
result[key] = value;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
result[key] = value;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return result;
|
|
321
|
+
}
|
|
322
|
+
static decodeResource(resource) {
|
|
323
|
+
const r = resource;
|
|
324
|
+
return {
|
|
325
|
+
attributes: this.decodeAttributes(r.attributes),
|
|
326
|
+
schemaUrl: typeof r.schema_url === 'string' ? r.schema_url : undefined,
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
static decodeScope(scope) {
|
|
330
|
+
const s = scope;
|
|
331
|
+
return {
|
|
332
|
+
name: typeof s.name === 'string' ? s.name : '',
|
|
333
|
+
version: typeof s.version === 'string' ? s.version : undefined,
|
|
334
|
+
attributes: this.decodeAttributes(s.attributes),
|
|
335
|
+
schemaUrl: typeof s.schema_url === 'string' ? s.schema_url : undefined,
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
static safeDecodeOTLPSpan(span, resource, scope) {
|
|
339
|
+
try {
|
|
340
|
+
if (!this.validateOTLPSpan(span)) {
|
|
341
|
+
return null;
|
|
342
|
+
}
|
|
343
|
+
return this.decodeOTLPSpan(span, resource, scope);
|
|
344
|
+
}
|
|
345
|
+
catch (error) {
|
|
346
|
+
console.error('[SpanProcessor] Failed to decode span:', error);
|
|
347
|
+
throw error;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
static batchProcessOTLPTraces(resourceSpans) {
|
|
351
|
+
const spans = [];
|
|
352
|
+
try {
|
|
353
|
+
for (const resourceSpan of resourceSpans) {
|
|
354
|
+
const resourceSpanObj = resourceSpan;
|
|
355
|
+
// Decode resource
|
|
356
|
+
if (!resourceSpanObj.resource) {
|
|
357
|
+
continue;
|
|
358
|
+
}
|
|
359
|
+
const resource = this.decodeResource(resourceSpanObj.resource);
|
|
360
|
+
// console.debug('[SpanProcessor] resource', resource);
|
|
361
|
+
const scopeSpansArray = resourceSpanObj.scope_spans;
|
|
362
|
+
if (!Array.isArray(scopeSpansArray)) {
|
|
363
|
+
continue;
|
|
364
|
+
}
|
|
365
|
+
for (const scopeSpan of scopeSpansArray) {
|
|
366
|
+
const scopeSpanObj = scopeSpan;
|
|
367
|
+
// Decode instrumentation scope
|
|
368
|
+
if (!scopeSpanObj.scope) {
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
const scope = this.decodeScope(scopeSpanObj.scope);
|
|
372
|
+
// console.debug('[SpanProcessor] scope', scope);
|
|
373
|
+
const spansArray = scopeSpanObj.spans;
|
|
374
|
+
if (!Array.isArray(spansArray)) {
|
|
375
|
+
continue;
|
|
376
|
+
}
|
|
377
|
+
for (const span of spansArray) {
|
|
378
|
+
const processedSpan = SpanProcessor.safeDecodeOTLPSpan(span, resource, scope);
|
|
379
|
+
if (processedSpan) {
|
|
380
|
+
spans.push(processedSpan);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
catch (error) {
|
|
387
|
+
console.error('[SpanProcessor] Failed to batch process spans:', error);
|
|
388
|
+
throw error;
|
|
389
|
+
}
|
|
390
|
+
return spans;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
exports.SpanProcessor = SpanProcessor;
|
|
394
|
+
SpanProcessor.warningPeriodStartTime = Date.now();
|
|
395
|
+
SpanProcessor.WARNING_PERIOD_MS = 5 * 60 * 1000; // 5 minutes
|
|
@@ -0,0 +1,128 @@
|
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const express_1 = __importDefault(require("express"));
|
|
16
|
+
const util_1 = require("util");
|
|
17
|
+
const zlib_1 = require("zlib");
|
|
18
|
+
const Trace_1 = require("../dao/Trace");
|
|
19
|
+
const socket_1 = require("../trpc/socket");
|
|
20
|
+
const trace_1 = require("./opentelemetry/proto/trace/v1/trace");
|
|
21
|
+
const processor_1 = require("./processor");
|
|
22
|
+
const gunzipAsync = (0, util_1.promisify)(zlib_1.gunzip);
|
|
23
|
+
const inflateAsync = (0, util_1.promisify)(zlib_1.inflate);
|
|
24
|
+
const otelRouter = express_1.default.Router();
|
|
25
|
+
// Request: POST /v1/traces
|
|
26
|
+
otelRouter.post('/traces', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
|
27
|
+
try {
|
|
28
|
+
console.debug(`[OTEL] Received OpenTelemetry traces request: ${req.method} ${req.path}`);
|
|
29
|
+
console.debug(`[OTEL] Content-Type: ${req.get('content-type')}`);
|
|
30
|
+
console.debug(`[OTEL] Content-Encoding: ${req.get('content-encoding')}`);
|
|
31
|
+
console.debug(`[OTEL] Content-Length: ${req.get('content-length')}`);
|
|
32
|
+
const contentType = req.get('content-type') || '';
|
|
33
|
+
const contentEncoding = req.get('content-encoding');
|
|
34
|
+
// Check content-type
|
|
35
|
+
if (!contentType ||
|
|
36
|
+
(!contentType.includes('application/x-protobuf') &&
|
|
37
|
+
!contentType.includes('application/json'))) {
|
|
38
|
+
return res.status(415).json({
|
|
39
|
+
error: 'Unsupported Media Type',
|
|
40
|
+
message: 'Content-Type must be application/x-protobuf or application/json',
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
// Check content-encoding
|
|
44
|
+
if (contentEncoding && !['gzip', 'deflate'].includes(contentEncoding)) {
|
|
45
|
+
return res.status(415).json({
|
|
46
|
+
error: 'Unsupported Content Encoding',
|
|
47
|
+
message: `Unsupported content encoding: ${contentEncoding}`,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
let body = req.body;
|
|
51
|
+
if (!body || body.length === 0) {
|
|
52
|
+
console.error('[OTEL] Empty request body');
|
|
53
|
+
return res.status(400).json({
|
|
54
|
+
error: 'Bad Request',
|
|
55
|
+
message: 'Empty request body',
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
// Handle compressed data
|
|
59
|
+
try {
|
|
60
|
+
if (contentEncoding === 'gzip') {
|
|
61
|
+
body = yield gunzipAsync(body);
|
|
62
|
+
}
|
|
63
|
+
else if (contentEncoding === 'deflate') {
|
|
64
|
+
body = yield inflateAsync(body);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
console.error('[OTEL] Failed to decompress request body:', error);
|
|
69
|
+
return res.status(400).json({
|
|
70
|
+
error: 'Bad Request',
|
|
71
|
+
message: 'Failed to decompress request body',
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
let resourceSpans;
|
|
75
|
+
// Parse the body based on content type
|
|
76
|
+
if (contentType.includes('application/x-protobuf')) {
|
|
77
|
+
try {
|
|
78
|
+
const traceData = trace_1.opentelemetry.proto.trace.v1.TracesData.deserializeBinary(body).toObject();
|
|
79
|
+
resourceSpans = traceData.resource_spans;
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
console.error('[OTEL] Failed to parse protobuf:', error);
|
|
83
|
+
return res.status(422).json({
|
|
84
|
+
error: 'Unprocessable Entity',
|
|
85
|
+
message: 'Failed to parse OpenTelemetry protobuf data',
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
else if (contentType.includes('application/json')) {
|
|
90
|
+
try {
|
|
91
|
+
const jsonData = JSON.parse(body.toString());
|
|
92
|
+
resourceSpans = jsonData.resourceSpans;
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
console.error('[OTEL] Failed to parse JSON:', error);
|
|
96
|
+
return res.status(422).json({
|
|
97
|
+
error: 'Unprocessable Entity',
|
|
98
|
+
message: 'Failed to parse JSON data',
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (!resourceSpans || !Array.isArray(resourceSpans)) {
|
|
103
|
+
return res.status(422).json({
|
|
104
|
+
error: 'Invalid or missing resourceSpans data',
|
|
105
|
+
message: 'Invalid OpenTelemetry data',
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
const spans = processor_1.SpanProcessor.batchProcessOTLPTraces(resourceSpans);
|
|
109
|
+
// Save spans to the databases
|
|
110
|
+
yield Trace_1.SpanDao.saveSpans(spans);
|
|
111
|
+
// Broadcast spans to the run room
|
|
112
|
+
socket_1.SocketManager.broadcastSpanDataToRunRoom(spans);
|
|
113
|
+
return res.status(200).json({
|
|
114
|
+
message: `Processed traces successfully`,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
console.error('Error processing OpenTelemetry traces:', error);
|
|
119
|
+
res.status(500);
|
|
120
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
|
|
121
|
+
res.statusMessage = errorMessage;
|
|
122
|
+
res.json({
|
|
123
|
+
error: 'Internal Server Error',
|
|
124
|
+
message: 'Failed to process traces',
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}));
|
|
128
|
+
exports.default = otelRouter;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReplyingStateManager = void 0;
|
|
4
|
+
class ReplyingStateManager {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.isReplying = false;
|
|
7
|
+
}
|
|
8
|
+
static getInstance() {
|
|
9
|
+
if (!ReplyingStateManager.instance) {
|
|
10
|
+
ReplyingStateManager.instance = new ReplyingStateManager();
|
|
11
|
+
}
|
|
12
|
+
return ReplyingStateManager.instance;
|
|
13
|
+
}
|
|
14
|
+
setReplyingState(state) {
|
|
15
|
+
this.isReplying = state;
|
|
16
|
+
}
|
|
17
|
+
getReplyingState() {
|
|
18
|
+
return this.isReplying;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.ReplyingStateManager = ReplyingStateManager;
|