@sentry/junior 0.96.0 → 0.97.0
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/dist/{agent-hooks-5URSMY3O.js → agent-hooks-XSUIVRQS.js} +8 -6
- package/dist/{reporting → api}/conversations/activity.d.ts +1 -1
- package/dist/api/conversations/detail-projection.d.ts +10 -0
- package/dist/api/conversations/detail.d.ts +3 -0
- package/dist/api/conversations/detail.query.d.ts +3 -0
- package/dist/api/conversations/list.d.ts +3 -0
- package/dist/api/conversations/list.query.d.ts +94 -0
- package/dist/api/conversations/projection.d.ts +14 -0
- package/dist/api/conversations/schema.d.ts +683 -0
- package/dist/{reporting → api}/conversations/shared.d.ts +1 -5
- package/dist/api/conversations/stats.d.ts +3 -0
- package/dist/api/conversations/stats.query.d.ts +3 -0
- package/dist/api/conversations/subagent.d.ts +3 -0
- package/dist/{reporting → api}/conversations/transcript.d.ts +4 -4
- package/dist/api/people/list.d.ts +1 -2
- package/dist/api/people/list.query.d.ts +3 -4
- package/dist/api/people/profile.d.ts +1 -2
- package/dist/api/people/profile.query.d.ts +3 -4
- package/dist/api/people/schema.d.ts +193 -0
- package/dist/api/people/shared.d.ts +31 -9
- package/dist/api/schema.d.ts +20 -0
- package/dist/api/schema.js +50 -0
- package/dist/api-reference.d.ts +4 -3
- package/dist/api.d.ts +3 -0
- package/dist/api.js +156 -0
- package/dist/app.d.ts +1 -4
- package/dist/app.js +100 -366
- package/dist/build/virtual-config.d.ts +2 -2
- package/dist/{catalog-runtime-MSMAYYIK.js → catalog-runtime-PFHVMHDR.js} +3 -2
- package/dist/chat/agent/resume.d.ts +3 -1
- package/dist/chat/agent/tools.d.ts +2 -1
- package/dist/chat/config.d.ts +1 -8
- package/dist/chat/conversations/history.d.ts +241 -27
- package/dist/chat/conversations/legacy-advisor-session.d.ts +7 -0
- package/dist/chat/conversations/legacy-import.d.ts +2 -2
- package/dist/chat/conversations/projection.d.ts +19 -3
- package/dist/chat/conversations/sql/legacy-history-import.d.ts +1 -1
- package/dist/chat/conversations/sql/store.d.ts +15 -9
- package/dist/chat/conversations/store.d.ts +9 -4
- package/dist/chat/model-profile.d.ts +14 -0
- package/dist/chat/pi/transcript.d.ts +5 -3
- package/dist/chat/resource-events/store.d.ts +2 -2
- package/dist/chat/services/context-compaction.d.ts +15 -0
- package/dist/chat/services/turn-result.d.ts +1 -0
- package/dist/chat/services/turn-session-record.d.ts +6 -6
- package/dist/chat/state/turn-session.d.ts +16 -5
- package/dist/chat/task-execution/store.d.ts +2 -2
- package/dist/chat/tools/handoff/tool.d.ts +45 -0
- package/dist/chat/tools/types.d.ts +7 -2
- package/dist/chat/usage.d.ts +25 -25
- package/dist/{chunk-RITD7E5L.js → chunk-35BNLDOJ.js} +338 -577
- package/dist/{chunk-PMNN6ST4.js → chunk-3ECW2K2O.js} +7 -2
- package/dist/{chunk-5C6XTTFI.js → chunk-3F4OPKGF.js} +89 -55
- package/dist/chunk-3V7OFJZC.js +264 -0
- package/dist/chunk-4ZNGQH7C.js +25 -0
- package/dist/{chunk-S5KZ5LPG.js → chunk-5HLDPVYS.js} +14 -447
- package/dist/{chunk-DZENG5ML.js → chunk-6U26PYI5.js} +24 -14
- package/dist/chunk-AUUCAFDE.js +546 -0
- package/dist/{chunk-6APU57E6.js → chunk-B3IT5END.js} +41 -260
- package/dist/chunk-CEA3A3UA.js +86 -0
- package/dist/{chunk-YDT7SNCN.js → chunk-D5KZYS4T.js} +1 -1
- package/dist/{chunk-YDVEH3SB.js → chunk-EEZCY5WX.js} +78 -28
- package/dist/{chunk-2NAZZPPS.js → chunk-EOWXRY5E.js} +1 -1
- package/dist/{chunk-GQ3GK22G.js → chunk-FBHZJFHI.js} +2 -2
- package/dist/{chunk-CZEX6KIQ.js → chunk-G3E7SCME.js} +0 -23
- package/dist/chunk-GUAP3H7O.js +319 -0
- package/dist/{chunk-BYZWPRJA.js → chunk-H66UCBPW.js} +6 -4
- package/dist/{chunk-L7CDEIVJ.js → chunk-LMJPRYHP.js} +4 -2
- package/dist/chunk-LUAE4MGW.js +199 -0
- package/dist/{chunk-GY34VGP5.js → chunk-LVA4I4H7.js} +3 -1
- package/dist/chunk-LVUKF5CE.js +63 -0
- package/dist/{chunk-AAZXTVJT.js → chunk-NG2AV7IB.js} +2 -72
- package/dist/chunk-ON6YKIQ7.js +260 -0
- package/dist/chunk-PDO5BLNM.js +22 -0
- package/dist/chunk-QNVHH5PU.js +20 -0
- package/dist/{chunk-P3YFQLEN.js → chunk-T533JLM3.js} +8 -10
- package/dist/chunk-UAMKJPDF.js +11 -0
- package/dist/chunk-VFH4ZKZT.js +66 -0
- package/dist/{chunk-UKHVMPX5.js → chunk-WGXMTFNU.js} +15 -17
- package/dist/{chunk-MNTINMWR.js → chunk-WJOSZOON.js} +184 -300
- package/dist/chunk-WTYEKPXU.js +451 -0
- package/dist/{chunk-IYM2SIVG.js → chunk-XIRPQQVE.js} +605 -363
- package/dist/cli/chat.js +24 -21
- package/dist/cli/check.js +4 -3
- package/dist/cli/init.js +12 -0
- package/dist/cli/plugins.js +12 -9
- package/dist/cli/snapshot-warmup.js +8 -6
- package/dist/cli/upgrade.js +265 -137
- package/dist/db/db.d.ts +4 -0
- package/dist/db/schema/conversations.d.ts +128 -0
- package/dist/db/schema.d.ts +129 -60
- package/dist/{db-2D6RMG67.js → db-BWXYIKFQ.js} +3 -3
- package/dist/detail-GA6NXWQJ.js +43 -0
- package/dist/discovery-RMHYSRL7.js +43 -0
- package/dist/handlers/health.d.ts +3 -0
- package/dist/instrumentation.js +1 -1
- package/dist/{legacy-import-VZ2MEGP7.js → legacy-import-3NQJVGQL.js} +4 -4
- package/dist/{api/people/list.js → list-A3WFRIYX.js} +26 -16
- package/dist/list-UXJI5Q5X.js +27 -0
- package/dist/nitro.d.ts +1 -1
- package/dist/nitro.js +2 -1
- package/dist/plugin-conversations-DDNGC35A.js +36 -0
- package/dist/{api/people/profile.js → profile-4RYDXWTF.js} +33 -18
- package/dist/reporting/plugin-conversations.d.ts +3 -0
- package/dist/reporting-schema.d.ts +140 -0
- package/dist/reporting.d.ts +12 -81
- package/dist/{runner-JZBRQP4F.js → runner-JALSYH2P.js} +17 -12
- package/dist/skills-MAZXZ2KE.js +26 -0
- package/dist/stats-XKXH3PTY.js +217 -0
- package/dist/subagent-TZ55XY37.js +48 -0
- package/dist/usage-schema.d.ts +25 -0
- package/dist/{validation-6XOOQGME.js → validation-FMEAEKCY.js} +4 -3
- package/migrations/0000_initial.sql +115 -0
- package/migrations/0001_conversation_metrics.sql +4 -0
- package/migrations/README.md +12 -30
- package/migrations/meta/0000_snapshot.json +1 -33
- package/migrations/meta/0001_snapshot.json +972 -0
- package/migrations/meta/_journal.json +9 -2
- package/package.json +14 -18
- package/dist/api/people/types.d.ts +0 -85
- package/dist/chat/advisor-request.d.ts +0 -4
- package/dist/chat/conversations/sql/migrations.d.ts +0 -22
- package/dist/chat/tools/advisor/session-store.d.ts +0 -9
- package/dist/chat/tools/advisor/tool.d.ts +0 -72
- package/dist/chunk-RAIB6WSG.js +0 -142
- package/dist/chunk-WM6KHPBQ.js +0 -48
- package/dist/db/schema/migrations.d.ts +0 -58
- package/dist/reporting/conversations/context.d.ts +0 -8
- package/dist/reporting/conversations/details.d.ts +0 -6
- package/dist/reporting/conversations/index.d.ts +0 -4
- package/dist/reporting/conversations/statistics.d.ts +0 -4
- package/dist/reporting/conversations/summaries.d.ts +0 -20
- package/dist/reporting/conversations/types.d.ts +0 -191
- package/dist/reporting/conversations.d.ts +0 -1
- package/dist/reporting.js +0 -1155
package/dist/reporting.js
DELETED
|
@@ -1,1155 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
GET,
|
|
3
|
-
buildSentryConversationUrl,
|
|
4
|
-
buildSentryTraceUrl,
|
|
5
|
-
formatSlackConversationRedactedLabel,
|
|
6
|
-
resolveSlackConversationContextFromThreadId
|
|
7
|
-
} from "./chunk-AAZXTVJT.js";
|
|
8
|
-
import {
|
|
9
|
-
unwrapAdvisorRequest
|
|
10
|
-
} from "./chunk-WM6KHPBQ.js";
|
|
11
|
-
import {
|
|
12
|
-
listAgentTurnSessionSummariesForConversation,
|
|
13
|
-
listAgentTurnSessionSummariesForConversations,
|
|
14
|
-
loadProjection,
|
|
15
|
-
projectSteps
|
|
16
|
-
} from "./chunk-MNTINMWR.js";
|
|
17
|
-
import "./chunk-5C6XTTFI.js";
|
|
18
|
-
import {
|
|
19
|
-
getPluginOperationalReports
|
|
20
|
-
} from "./chunk-S5KZ5LPG.js";
|
|
21
|
-
import "./chunk-2NAZZPPS.js";
|
|
22
|
-
import "./chunk-CZEX6KIQ.js";
|
|
23
|
-
import {
|
|
24
|
-
getAgentStepStore,
|
|
25
|
-
getConversationMessageStore,
|
|
26
|
-
getConversationStore
|
|
27
|
-
} from "./chunk-RITD7E5L.js";
|
|
28
|
-
import {
|
|
29
|
-
unwrapCurrentInstruction
|
|
30
|
-
} from "./chunk-YDVEH3SB.js";
|
|
31
|
-
import {
|
|
32
|
-
canExposeConversationPayload,
|
|
33
|
-
parseSlackThreadId,
|
|
34
|
-
resolveConversationPrivacy
|
|
35
|
-
} from "./chunk-GY34VGP5.js";
|
|
36
|
-
import "./chunk-B7PUBQQM.js";
|
|
37
|
-
import {
|
|
38
|
-
discoverSkills
|
|
39
|
-
} from "./chunk-PMNN6ST4.js";
|
|
40
|
-
import {
|
|
41
|
-
pluginCatalogRuntime
|
|
42
|
-
} from "./chunk-L7CDEIVJ.js";
|
|
43
|
-
import "./chunk-I35CTGPO.js";
|
|
44
|
-
import {
|
|
45
|
-
isRecord
|
|
46
|
-
} from "./chunk-OB42YVAE.js";
|
|
47
|
-
import "./chunk-6GWA276C.js";
|
|
48
|
-
import {
|
|
49
|
-
homeDir
|
|
50
|
-
} from "./chunk-6APU57E6.js";
|
|
51
|
-
import "./chunk-7FBGKXPE.js";
|
|
52
|
-
import "./chunk-MLKGABMK.js";
|
|
53
|
-
|
|
54
|
-
// src/reporting.ts
|
|
55
|
-
import { readFileSync } from "fs";
|
|
56
|
-
import path from "path";
|
|
57
|
-
|
|
58
|
-
// src/reporting/conversations/context.ts
|
|
59
|
-
function conversationStore(options = {}) {
|
|
60
|
-
return options.conversationStore ?? getConversationStore();
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// src/reporting/conversations/transcript.ts
|
|
64
|
-
var SAFE_METADATA_KEY_LIMIT = 20;
|
|
65
|
-
function textPart(text) {
|
|
66
|
-
return { type: "text", text };
|
|
67
|
-
}
|
|
68
|
-
function recordField(value, names) {
|
|
69
|
-
for (const name of names) {
|
|
70
|
-
if (value[name] !== void 0) {
|
|
71
|
-
return value[name];
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return void 0;
|
|
75
|
-
}
|
|
76
|
-
function normalizeTranscriptPart(part, options = {}) {
|
|
77
|
-
const displayText = (text) => {
|
|
78
|
-
if (options.unwrapCurrentTask) {
|
|
79
|
-
const instruction = unwrapCurrentInstruction(text);
|
|
80
|
-
if (instruction !== void 0) return instruction;
|
|
81
|
-
}
|
|
82
|
-
if (options.unwrapAdvisorTask) return unwrapAdvisorRequest(text) ?? text;
|
|
83
|
-
return text;
|
|
84
|
-
};
|
|
85
|
-
if (typeof part === "string") {
|
|
86
|
-
return textPart(displayText(part));
|
|
87
|
-
}
|
|
88
|
-
if (!isRecord(part)) {
|
|
89
|
-
return { type: "unknown", output: part };
|
|
90
|
-
}
|
|
91
|
-
const rawType = typeof part.type === "string" ? part.type : "unknown";
|
|
92
|
-
if (rawType === "text") {
|
|
93
|
-
const text = recordField(part, ["text", "content"]);
|
|
94
|
-
return textPart(
|
|
95
|
-
typeof text === "string" ? displayText(text) : JSON.stringify(text) ?? ""
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
if (rawType === "toolCall") {
|
|
99
|
-
return {
|
|
100
|
-
type: "tool_call",
|
|
101
|
-
...typeof part.id === "string" ? { id: part.id } : {},
|
|
102
|
-
...typeof part.name === "string" ? { name: part.name } : {},
|
|
103
|
-
input: recordField(part, ["arguments", "input", "args"])
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
if (rawType === "toolResult") {
|
|
107
|
-
return {
|
|
108
|
-
type: "tool_result",
|
|
109
|
-
...typeof part.id === "string" ? { id: part.id } : {},
|
|
110
|
-
...typeof part.name === "string" ? { name: part.name } : {},
|
|
111
|
-
output: recordField(part, ["result", "output", "content"])
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
if (rawType === "thinking") {
|
|
115
|
-
return {
|
|
116
|
-
type: "thinking",
|
|
117
|
-
output: recordField(part, ["thinking", "text", "content", "output"])
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
return {
|
|
121
|
-
type: "unknown",
|
|
122
|
-
...rawType !== "unknown" ? { sourceType: rawType } : {},
|
|
123
|
-
output: part
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
function normalizeToolResultMessage(record) {
|
|
127
|
-
const content = record.content;
|
|
128
|
-
let output = content;
|
|
129
|
-
if (Array.isArray(content) && content.length === 1 && isRecord(content[0])) {
|
|
130
|
-
const extracted = recordField(content[0], [
|
|
131
|
-
"text",
|
|
132
|
-
"content",
|
|
133
|
-
"output",
|
|
134
|
-
"result"
|
|
135
|
-
]);
|
|
136
|
-
output = extracted !== void 0 ? extracted : content;
|
|
137
|
-
}
|
|
138
|
-
return {
|
|
139
|
-
type: "tool_result",
|
|
140
|
-
...typeof record.toolCallId === "string" ? { id: record.toolCallId } : {},
|
|
141
|
-
...typeof record.name === "string" ? { name: record.name } : typeof record.toolName === "string" ? { name: record.toolName } : {},
|
|
142
|
-
output
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
function normalizeTranscriptMessage(message, options = {}) {
|
|
146
|
-
const record = message;
|
|
147
|
-
const content = record.content;
|
|
148
|
-
const role = transcriptRole(record.role);
|
|
149
|
-
return {
|
|
150
|
-
role,
|
|
151
|
-
...typeof record.timestamp === "number" ? { timestamp: record.timestamp } : {},
|
|
152
|
-
parts: role === "toolResult" ? [normalizeToolResultMessage(record)] : Array.isArray(content) ? content.map(
|
|
153
|
-
(part) => normalizeTranscriptPart(part, {
|
|
154
|
-
unwrapAdvisorTask: options.unwrapAdvisorTask && role === "user",
|
|
155
|
-
unwrapCurrentTask: role === "user"
|
|
156
|
-
})
|
|
157
|
-
) : [
|
|
158
|
-
normalizeTranscriptPart(content, {
|
|
159
|
-
unwrapAdvisorTask: options.unwrapAdvisorTask && role === "user",
|
|
160
|
-
unwrapCurrentTask: role === "user"
|
|
161
|
-
})
|
|
162
|
-
]
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
function transcriptRole(role) {
|
|
166
|
-
return role === "assistant" || role === "system" || role === "tool" || role === "toolResult" || role === "user" ? role : "unknown";
|
|
167
|
-
}
|
|
168
|
-
function serializedChars(value) {
|
|
169
|
-
if (typeof value === "string") return value.length;
|
|
170
|
-
return JSON.stringify(value)?.length ?? 0;
|
|
171
|
-
}
|
|
172
|
-
function serializedBytes(value) {
|
|
173
|
-
const serialized = typeof value === "string" ? value : JSON.stringify(value);
|
|
174
|
-
return new TextEncoder().encode(serialized ?? "").byteLength;
|
|
175
|
-
}
|
|
176
|
-
function payloadType(value) {
|
|
177
|
-
return Array.isArray(value) ? "array" : typeof value;
|
|
178
|
-
}
|
|
179
|
-
function payloadKeys(value) {
|
|
180
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
181
|
-
return void 0;
|
|
182
|
-
}
|
|
183
|
-
const keys = Object.keys(value).slice(
|
|
184
|
-
0,
|
|
185
|
-
SAFE_METADATA_KEY_LIMIT
|
|
186
|
-
);
|
|
187
|
-
return keys.length > 0 ? keys : void 0;
|
|
188
|
-
}
|
|
189
|
-
function redactedPayloadFields(prefix, value) {
|
|
190
|
-
const keys = payloadKeys(value);
|
|
191
|
-
return {
|
|
192
|
-
[`${prefix}Type`]: payloadType(value),
|
|
193
|
-
[`${prefix}SizeBytes`]: serializedBytes(value),
|
|
194
|
-
[`${prefix}SizeChars`]: serializedChars(value),
|
|
195
|
-
...keys ? { [`${prefix}Keys`]: keys } : {}
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
function redactTranscriptPart(part) {
|
|
199
|
-
if (part.type === "text") {
|
|
200
|
-
return {
|
|
201
|
-
type: "text",
|
|
202
|
-
redacted: true,
|
|
203
|
-
bytes: serializedBytes(part.text ?? ""),
|
|
204
|
-
chars: serializedChars(part.text ?? "")
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
if (part.type === "thinking") {
|
|
208
|
-
return {
|
|
209
|
-
type: "thinking",
|
|
210
|
-
redacted: true,
|
|
211
|
-
...redactedPayloadFields("output", part.output)
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
if (part.type === "tool_call") {
|
|
215
|
-
return {
|
|
216
|
-
type: "tool_call",
|
|
217
|
-
redacted: true,
|
|
218
|
-
...part.id ? { id: part.id } : {},
|
|
219
|
-
...part.name ? { name: part.name } : {},
|
|
220
|
-
...redactedPayloadFields("input", part.input)
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
if (part.type === "tool_result") {
|
|
224
|
-
return {
|
|
225
|
-
type: "tool_result",
|
|
226
|
-
redacted: true,
|
|
227
|
-
...part.id ? { id: part.id } : {},
|
|
228
|
-
...part.name ? { name: part.name } : {},
|
|
229
|
-
...redactedPayloadFields("output", part.output)
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
return {
|
|
233
|
-
type: "unknown",
|
|
234
|
-
redacted: true,
|
|
235
|
-
...part.sourceType ? { sourceType: part.sourceType } : {},
|
|
236
|
-
...redactedPayloadFields("output", part.output ?? part.input ?? part.text)
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
function redactTranscriptMessage(message) {
|
|
240
|
-
return {
|
|
241
|
-
role: message.role,
|
|
242
|
-
...typeof message.timestamp === "number" ? { timestamp: message.timestamp } : {},
|
|
243
|
-
parts: message.parts.map(redactTranscriptPart)
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
function isConversationMessageRole(role) {
|
|
247
|
-
return role === "user" || role === "assistant";
|
|
248
|
-
}
|
|
249
|
-
function hasTextPart(message) {
|
|
250
|
-
return message.parts.some((part) => {
|
|
251
|
-
if (part.type !== "text") return false;
|
|
252
|
-
if (part.redacted) return true;
|
|
253
|
-
return typeof part.text === "string" && part.text.trim().length > 0;
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
function isConversationMessage(message) {
|
|
257
|
-
if (!isConversationMessageRole(message.role)) return false;
|
|
258
|
-
if (message.role === "assistant") return hasTextPart(message);
|
|
259
|
-
return message.parts.length > 0;
|
|
260
|
-
}
|
|
261
|
-
function countConversationMessages(transcript) {
|
|
262
|
-
return transcript.filter(isConversationMessage).length;
|
|
263
|
-
}
|
|
264
|
-
function traceIdFromTranscript(transcript) {
|
|
265
|
-
for (const message of transcript) {
|
|
266
|
-
for (const part of message.parts) {
|
|
267
|
-
const text = part.text ?? (typeof part.output === "string" ? part.output : typeof part.input === "string" ? part.input : void 0);
|
|
268
|
-
const match = text?.match(
|
|
269
|
-
/\btrace[_-]?id["']?\s*[:=]\s*["']?([a-f0-9]{16,32})\b/i
|
|
270
|
-
);
|
|
271
|
-
if (match?.[1]) {
|
|
272
|
-
return match[1];
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
return void 0;
|
|
277
|
-
}
|
|
278
|
-
function subagentTranscriptReport(activity, options = {}) {
|
|
279
|
-
return {
|
|
280
|
-
type: "subagent",
|
|
281
|
-
...options.subagentConversationId ? { subagentConversationId: options.subagentConversationId } : {},
|
|
282
|
-
createdAt: activity.createdAt,
|
|
283
|
-
id: activity.id,
|
|
284
|
-
...activity.modelId ? { modelId: activity.modelId } : {},
|
|
285
|
-
status: activity.status,
|
|
286
|
-
...options.subagentSentryConversationUrl ? { subagentSentryConversationUrl: options.subagentSentryConversationUrl } : {},
|
|
287
|
-
subagentKind: activity.subagentKind,
|
|
288
|
-
transcript: options.transcript ?? [],
|
|
289
|
-
transcriptAvailable: Boolean(options.transcript?.length),
|
|
290
|
-
...activity.endedAt ? { endedAt: activity.endedAt } : {},
|
|
291
|
-
...activity.outcome ? { outcome: activity.outcome } : {},
|
|
292
|
-
...activity.parentToolCallId ? { parentToolCallId: activity.parentToolCallId } : {},
|
|
293
|
-
...activity.reasoningLevel ? { reasoningLevel: activity.reasoningLevel } : {},
|
|
294
|
-
...options.transcriptMessageCount !== void 0 ? { transcriptMessageCount: options.transcriptMessageCount } : {},
|
|
295
|
-
...options.transcriptRedacted ? { transcriptRedacted: options.transcriptRedacted } : {},
|
|
296
|
-
...options.transcriptRedactionReason ? { transcriptRedactionReason: options.transcriptRedactionReason } : {},
|
|
297
|
-
...options.transcriptExpired ? { transcriptExpired: options.transcriptExpired } : {},
|
|
298
|
-
...options.transcriptExpiredAt ? { transcriptExpiredAt: options.transcriptExpiredAt } : {},
|
|
299
|
-
...options.unavailableReason ? { unavailableReason: options.unavailableReason } : {}
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
// src/reporting/conversations/activity.ts
|
|
304
|
-
function toolResultStatuses(messages) {
|
|
305
|
-
const statuses = /* @__PURE__ */ new Map();
|
|
306
|
-
for (const message of messages) {
|
|
307
|
-
const record = message;
|
|
308
|
-
if (record.role !== "toolResult" || typeof record.toolCallId !== "string") {
|
|
309
|
-
continue;
|
|
310
|
-
}
|
|
311
|
-
statuses.set(record.toolCallId, record.isError ? "error" : "completed");
|
|
312
|
-
}
|
|
313
|
-
return statuses;
|
|
314
|
-
}
|
|
315
|
-
function activityPayloadFields(args, canExposePayload) {
|
|
316
|
-
if (args === void 0) {
|
|
317
|
-
return {};
|
|
318
|
-
}
|
|
319
|
-
return canExposePayload ? { args } : { redacted: true, ...redactedPayloadFields("input", args) };
|
|
320
|
-
}
|
|
321
|
-
function buildConversationActivityFromSteps(args) {
|
|
322
|
-
const toolStatuses = toolResultStatuses(args.messages);
|
|
323
|
-
const subagentEnds = /* @__PURE__ */ new Map();
|
|
324
|
-
const subagentsByToolCallId = /* @__PURE__ */ new Map();
|
|
325
|
-
const orphanSubagents = [];
|
|
326
|
-
for (const step of args.steps) {
|
|
327
|
-
if (step.entry.type === "subagent_ended") {
|
|
328
|
-
subagentEnds.set(
|
|
329
|
-
step.entry.subagentInvocationId,
|
|
330
|
-
step
|
|
331
|
-
);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
for (const step of args.steps) {
|
|
335
|
-
if (step.entry.type !== "subagent_started") {
|
|
336
|
-
continue;
|
|
337
|
-
}
|
|
338
|
-
const start = step;
|
|
339
|
-
const parentStatus = start.entry.parentToolCallId ? toolStatuses.get(start.entry.parentToolCallId) : void 0;
|
|
340
|
-
const activity = subagentActivityFromSteps(
|
|
341
|
-
start,
|
|
342
|
-
subagentEnds.get(start.entry.subagentInvocationId),
|
|
343
|
-
{ canExposeTranscript: args.canExposePayload, parentStatus }
|
|
344
|
-
);
|
|
345
|
-
if (start.entry.parentToolCallId) {
|
|
346
|
-
subagentsByToolCallId.set(start.entry.parentToolCallId, [
|
|
347
|
-
...subagentsByToolCallId.get(start.entry.parentToolCallId) ?? [],
|
|
348
|
-
activity
|
|
349
|
-
]);
|
|
350
|
-
continue;
|
|
351
|
-
}
|
|
352
|
-
orphanSubagents.push(activity);
|
|
353
|
-
}
|
|
354
|
-
const rows = [];
|
|
355
|
-
for (const step of args.steps) {
|
|
356
|
-
if (step.entry.type !== "tool_execution_started") {
|
|
357
|
-
continue;
|
|
358
|
-
}
|
|
359
|
-
rows.push({
|
|
360
|
-
type: "tool_execution",
|
|
361
|
-
id: step.entry.toolCallId,
|
|
362
|
-
toolCallId: step.entry.toolCallId,
|
|
363
|
-
toolName: step.entry.toolName,
|
|
364
|
-
createdAt: new Date(step.createdAtMs).toISOString(),
|
|
365
|
-
status: toolStatuses.get(step.entry.toolCallId) ?? "running",
|
|
366
|
-
subagents: subagentsByToolCallId.get(step.entry.toolCallId) ?? [],
|
|
367
|
-
...activityPayloadFields(step.entry.args, args.canExposePayload)
|
|
368
|
-
});
|
|
369
|
-
}
|
|
370
|
-
return [...rows, ...orphanSubagents].sort(
|
|
371
|
-
(left, right) => Date.parse(left.createdAt) - Date.parse(right.createdAt) || left.id.localeCompare(right.id)
|
|
372
|
-
);
|
|
373
|
-
}
|
|
374
|
-
function subagentActivityFromSteps(start, end, options = {}) {
|
|
375
|
-
return {
|
|
376
|
-
type: "subagent",
|
|
377
|
-
id: start.entry.subagentInvocationId,
|
|
378
|
-
subagentKind: start.entry.subagentKind,
|
|
379
|
-
...start.entry.modelId ? { modelId: start.entry.modelId } : {},
|
|
380
|
-
...start.entry.parentToolCallId ? { parentToolCallId: start.entry.parentToolCallId } : {},
|
|
381
|
-
...start.entry.reasoningLevel ? { reasoningLevel: start.entry.reasoningLevel } : {},
|
|
382
|
-
createdAt: new Date(start.createdAtMs).toISOString(),
|
|
383
|
-
...end ? {
|
|
384
|
-
endedAt: new Date(end.createdAtMs).toISOString(),
|
|
385
|
-
outcome: end.entry.outcome,
|
|
386
|
-
status: end.entry.outcome,
|
|
387
|
-
// Every subagent is a child conversation whose transcript loads on
|
|
388
|
-
// demand; expose the affordance only when the parent is public.
|
|
389
|
-
...options.canExposeTranscript ? { transcriptAvailable: true } : {}
|
|
390
|
-
} : { status: options.parentStatus ?? "running" }
|
|
391
|
-
};
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
// src/reporting/conversations/shared.ts
|
|
395
|
-
function reportTime(value) {
|
|
396
|
-
const time = Date.parse(value);
|
|
397
|
-
return Number.isFinite(time) ? time : void 0;
|
|
398
|
-
}
|
|
399
|
-
function slackStatsLocationLabel(input) {
|
|
400
|
-
const channelId = input.channel;
|
|
401
|
-
if (!channelId) return void 0;
|
|
402
|
-
if (input.channelNameRedacted && input.channelName) {
|
|
403
|
-
return input.channelName;
|
|
404
|
-
}
|
|
405
|
-
const name = input.channelName?.replace(/^#/, "");
|
|
406
|
-
if (channelId.startsWith("D")) return "Direct Message";
|
|
407
|
-
if (channelId.startsWith("C")) return name ? `#${name}` : "Public Channel";
|
|
408
|
-
if (channelId.startsWith("G")) {
|
|
409
|
-
if (name?.startsWith("mpdm-")) return "Group DM";
|
|
410
|
-
return "Private Channel";
|
|
411
|
-
}
|
|
412
|
-
return name || channelId;
|
|
413
|
-
}
|
|
414
|
-
function surfaceFallbackLabel(surface) {
|
|
415
|
-
if (surface === "scheduler") return "Scheduler";
|
|
416
|
-
if (surface === "api") return "API";
|
|
417
|
-
if (surface === "internal") return "Internal";
|
|
418
|
-
return "Conversation";
|
|
419
|
-
}
|
|
420
|
-
function newestRun(runs) {
|
|
421
|
-
return [...runs].sort(
|
|
422
|
-
(left, right) => (reportTime(right.lastSeenAt) ?? 0) - (reportTime(left.lastSeenAt) ?? 0) || right.id.localeCompare(left.id)
|
|
423
|
-
)[0];
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
// src/reporting/conversations/summaries.ts
|
|
427
|
-
var HUNG_TURN_PROGRESS_MS = 5 * 60 * 1e3;
|
|
428
|
-
var PRIVATE_CONVERSATION_LABEL = "Private Conversation";
|
|
429
|
-
var CONVERSATION_FEED_LIMIT = 50;
|
|
430
|
-
function privateConversationLabel(slackConversation) {
|
|
431
|
-
if (!slackConversation) {
|
|
432
|
-
return PRIVATE_CONVERSATION_LABEL;
|
|
433
|
-
}
|
|
434
|
-
return slackConversation.visibility === "private" ? formatSlackConversationRedactedLabel(slackConversation) ?? PRIVATE_CONVERSATION_LABEL : PRIVATE_CONVERSATION_LABEL;
|
|
435
|
-
}
|
|
436
|
-
function surfaceFromConversationId(conversationId) {
|
|
437
|
-
if (parseSlackThreadId(conversationId)) return "slack";
|
|
438
|
-
if (conversationId.startsWith("scheduler:")) return "scheduler";
|
|
439
|
-
if (conversationId.startsWith("api:")) return "api";
|
|
440
|
-
return "internal";
|
|
441
|
-
}
|
|
442
|
-
function surfaceFromSource(source, conversationId) {
|
|
443
|
-
if (source === "slack" || source === "api" || source === "scheduler") {
|
|
444
|
-
return source;
|
|
445
|
-
}
|
|
446
|
-
return surfaceFromConversationId(conversationId);
|
|
447
|
-
}
|
|
448
|
-
function actorIdentityReport(actor) {
|
|
449
|
-
if (!actor) return void 0;
|
|
450
|
-
if ("name" in actor) {
|
|
451
|
-
return { fullName: actor.name };
|
|
452
|
-
}
|
|
453
|
-
if ("userId" in actor) {
|
|
454
|
-
const identity2 = {
|
|
455
|
-
...actor.email !== void 0 ? { email: actor.email } : {},
|
|
456
|
-
...actor.fullName !== void 0 ? { fullName: actor.fullName } : {},
|
|
457
|
-
...actor.platform === "slack" ? { slackUserId: actor.userId } : {},
|
|
458
|
-
...actor.platform === "slack" && actor.userName !== void 0 ? { slackUserName: actor.userName } : {}
|
|
459
|
-
};
|
|
460
|
-
return Object.keys(identity2).length > 0 ? identity2 : void 0;
|
|
461
|
-
}
|
|
462
|
-
const identity = {
|
|
463
|
-
...actor.email !== void 0 ? { email: actor.email } : {},
|
|
464
|
-
...actor.fullName !== void 0 ? { fullName: actor.fullName } : {},
|
|
465
|
-
...actor.slackUserId !== void 0 ? { slackUserId: actor.slackUserId } : {},
|
|
466
|
-
...actor.slackUserName !== void 0 ? { slackUserName: actor.slackUserName } : {}
|
|
467
|
-
};
|
|
468
|
-
return Object.keys(identity).length > 0 ? identity : void 0;
|
|
469
|
-
}
|
|
470
|
-
function statusFromConversation(conversation, fallback, nowMs) {
|
|
471
|
-
if (fallback) {
|
|
472
|
-
return fallback;
|
|
473
|
-
}
|
|
474
|
-
if (conversation.execution.status === "idle") {
|
|
475
|
-
return "completed";
|
|
476
|
-
}
|
|
477
|
-
if (conversation.execution.status === "failed") {
|
|
478
|
-
return "failed";
|
|
479
|
-
}
|
|
480
|
-
const updatedAtMs = conversation.execution.updatedAtMs ?? conversation.updatedAtMs;
|
|
481
|
-
if (conversation.execution.status === "running" && nowMs - updatedAtMs > HUNG_TURN_PROGRESS_MS) {
|
|
482
|
-
return "hung";
|
|
483
|
-
}
|
|
484
|
-
return "active";
|
|
485
|
-
}
|
|
486
|
-
function titleFromConversation(args) {
|
|
487
|
-
const slackThread = parseSlackThreadId(args.conversation.conversationId);
|
|
488
|
-
const effectiveChannelName = args.conversation.channelName;
|
|
489
|
-
const slackConversation = resolveSlackConversationContextFromThreadId({
|
|
490
|
-
threadId: args.conversation.conversationId,
|
|
491
|
-
channelName: effectiveChannelName
|
|
492
|
-
});
|
|
493
|
-
const privateLabel = resolveConversationPrivacy({
|
|
494
|
-
conversationId: args.conversation.conversationId,
|
|
495
|
-
visibility: args.conversation.visibility
|
|
496
|
-
}) !== "public" ? privateConversationLabel(slackConversation) : void 0;
|
|
497
|
-
return privateLabel ?? args.conversation.title ?? slackStatsLocationLabel({
|
|
498
|
-
channel: slackThread?.channelId,
|
|
499
|
-
channelName: effectiveChannelName
|
|
500
|
-
}) ?? surfaceFallbackLabel(args.surface);
|
|
501
|
-
}
|
|
502
|
-
function channelNameFromConversation(conversation) {
|
|
503
|
-
const effectiveChannelName = conversation.channelName;
|
|
504
|
-
const slackThread = parseSlackThreadId(conversation.conversationId);
|
|
505
|
-
if (!effectiveChannelName && !slackThread) {
|
|
506
|
-
return void 0;
|
|
507
|
-
}
|
|
508
|
-
const slackConversation = resolveSlackConversationContextFromThreadId({
|
|
509
|
-
threadId: conversation.conversationId,
|
|
510
|
-
channelName: effectiveChannelName
|
|
511
|
-
});
|
|
512
|
-
if (resolveConversationPrivacy({
|
|
513
|
-
conversationId: conversation.conversationId,
|
|
514
|
-
visibility: conversation.visibility
|
|
515
|
-
}) !== "public") {
|
|
516
|
-
return privateConversationLabel(slackConversation);
|
|
517
|
-
}
|
|
518
|
-
return effectiveChannelName;
|
|
519
|
-
}
|
|
520
|
-
function channelNameRedactedFromConversation(conversation) {
|
|
521
|
-
const effectiveChannelName = conversation.channelName;
|
|
522
|
-
const slackThread = parseSlackThreadId(conversation.conversationId);
|
|
523
|
-
if (!effectiveChannelName && !slackThread) {
|
|
524
|
-
return false;
|
|
525
|
-
}
|
|
526
|
-
return resolveConversationPrivacy({
|
|
527
|
-
conversationId: conversation.conversationId,
|
|
528
|
-
visibility: conversation.visibility
|
|
529
|
-
}) !== "public";
|
|
530
|
-
}
|
|
531
|
-
function sessionReportFromConversation(conversation, nowMs) {
|
|
532
|
-
const surface = surfaceFromSource(
|
|
533
|
-
conversation.source,
|
|
534
|
-
conversation.conversationId
|
|
535
|
-
);
|
|
536
|
-
const actorIdentity = actorIdentityReport(conversation.actor);
|
|
537
|
-
const slackThread = parseSlackThreadId(conversation.conversationId);
|
|
538
|
-
const channelName = channelNameFromConversation(conversation);
|
|
539
|
-
const channelNameRedacted = channelNameRedactedFromConversation(conversation);
|
|
540
|
-
return {
|
|
541
|
-
conversationId: conversation.conversationId,
|
|
542
|
-
cumulativeDurationMs: 0,
|
|
543
|
-
displayTitle: titleFromConversation({ conversation, surface }),
|
|
544
|
-
id: conversation.conversationId,
|
|
545
|
-
lastProgressAt: new Date(
|
|
546
|
-
conversation.execution.updatedAtMs ?? conversation.updatedAtMs
|
|
547
|
-
).toISOString(),
|
|
548
|
-
lastSeenAt: new Date(conversation.lastActivityAtMs).toISOString(),
|
|
549
|
-
startedAt: new Date(conversation.createdAtMs).toISOString(),
|
|
550
|
-
status: statusFromConversation(conversation, void 0, nowMs),
|
|
551
|
-
surface,
|
|
552
|
-
...actorIdentity ? { actorIdentity } : {},
|
|
553
|
-
...slackThread ? { channel: slackThread.channelId } : {},
|
|
554
|
-
...channelName ? { channelName } : {},
|
|
555
|
-
...channelNameRedacted ? { channelNameRedacted: true } : {}
|
|
556
|
-
};
|
|
557
|
-
}
|
|
558
|
-
function statusFromTurnSummary(summary, nowMs) {
|
|
559
|
-
if (summary.state === "running" && nowMs - summary.lastProgressAtMs > HUNG_TURN_PROGRESS_MS) {
|
|
560
|
-
return "hung";
|
|
561
|
-
}
|
|
562
|
-
if (summary.state === "running" || summary.state === "awaiting_resume") {
|
|
563
|
-
return "active";
|
|
564
|
-
}
|
|
565
|
-
if (summary.state === "abandoned") {
|
|
566
|
-
return "superseded";
|
|
567
|
-
}
|
|
568
|
-
return summary.state;
|
|
569
|
-
}
|
|
570
|
-
function sessionReportFromTurnSummary(conversation, summary, nowMs) {
|
|
571
|
-
const base = sessionReportFromConversation(conversation, nowMs);
|
|
572
|
-
if (summary.actor !== void 0) {
|
|
573
|
-
const actorIdentity = actorIdentityReport(summary.actor);
|
|
574
|
-
if (actorIdentity) {
|
|
575
|
-
base.actorIdentity = actorIdentity;
|
|
576
|
-
} else {
|
|
577
|
-
delete base.actorIdentity;
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
return {
|
|
581
|
-
...base,
|
|
582
|
-
cumulativeDurationMs: summary.cumulativeDurationMs,
|
|
583
|
-
...summary.cumulativeUsage ? { cumulativeUsage: summary.cumulativeUsage } : {},
|
|
584
|
-
id: summary.sessionId,
|
|
585
|
-
lastProgressAt: new Date(summary.lastProgressAtMs).toISOString(),
|
|
586
|
-
lastSeenAt: new Date(summary.updatedAtMs).toISOString(),
|
|
587
|
-
startedAt: new Date(summary.startedAtMs).toISOString(),
|
|
588
|
-
status: statusFromTurnSummary(summary, nowMs),
|
|
589
|
-
surface: summary.surface ?? base.surface,
|
|
590
|
-
...summary.state === "completed" ? { completedAt: new Date(summary.updatedAtMs).toISOString() } : {},
|
|
591
|
-
...summary.traceId ? { traceId: summary.traceId } : {}
|
|
592
|
-
};
|
|
593
|
-
}
|
|
594
|
-
async function reportsFromConversations(args) {
|
|
595
|
-
const reports = /* @__PURE__ */ new Map();
|
|
596
|
-
for (const conversation of args.conversations) {
|
|
597
|
-
reports.set(conversation.conversationId, [
|
|
598
|
-
sessionReportFromConversation(conversation, args.nowMs)
|
|
599
|
-
]);
|
|
600
|
-
}
|
|
601
|
-
return reports;
|
|
602
|
-
}
|
|
603
|
-
async function readConversationFeed(options = {}) {
|
|
604
|
-
const store = conversationStore(options);
|
|
605
|
-
const nowMs = Date.now();
|
|
606
|
-
const conversations = await store.listByActivity({
|
|
607
|
-
limit: CONVERSATION_FEED_LIMIT
|
|
608
|
-
});
|
|
609
|
-
const reportsByConversation = await reportsFromConversations({
|
|
610
|
-
conversations,
|
|
611
|
-
nowMs
|
|
612
|
-
});
|
|
613
|
-
return {
|
|
614
|
-
source: "conversation_index",
|
|
615
|
-
generatedAt: new Date(nowMs).toISOString(),
|
|
616
|
-
conversations: conversations.map(
|
|
617
|
-
(conversation) => newestRun(
|
|
618
|
-
reportsByConversation.get(conversation.conversationId) ?? [
|
|
619
|
-
sessionReportFromConversation(conversation, nowMs)
|
|
620
|
-
]
|
|
621
|
-
)
|
|
622
|
-
)
|
|
623
|
-
};
|
|
624
|
-
}
|
|
625
|
-
async function listRecentConversationSummaries(options = {}) {
|
|
626
|
-
const store = conversationStore(options);
|
|
627
|
-
const nowMs = Date.now();
|
|
628
|
-
const limit = Math.max(0, Math.min(100, Math.floor(options.limit ?? 25)));
|
|
629
|
-
const conversations = await store.listByActivity({
|
|
630
|
-
limit
|
|
631
|
-
});
|
|
632
|
-
const reportsByConversation = await reportsFromConversations({
|
|
633
|
-
conversations,
|
|
634
|
-
nowMs
|
|
635
|
-
});
|
|
636
|
-
return conversations.map((conversation) => {
|
|
637
|
-
const surface = surfaceFromSource(
|
|
638
|
-
conversation.source,
|
|
639
|
-
conversation.conversationId
|
|
640
|
-
);
|
|
641
|
-
const channelName = channelNameFromConversation(conversation);
|
|
642
|
-
const channelNameRedacted = channelNameRedactedFromConversation(conversation);
|
|
643
|
-
const report = newestRun(
|
|
644
|
-
reportsByConversation.get(conversation.conversationId) ?? [
|
|
645
|
-
sessionReportFromConversation(conversation, nowMs)
|
|
646
|
-
]
|
|
647
|
-
);
|
|
648
|
-
return {
|
|
649
|
-
conversationId: conversation.conversationId,
|
|
650
|
-
displayTitle: titleFromConversation({ conversation, surface }),
|
|
651
|
-
lastActivityAt: new Date(conversation.lastActivityAtMs).toISOString(),
|
|
652
|
-
lastUpdatedAt: new Date(
|
|
653
|
-
conversation.execution.updatedAtMs ?? conversation.updatedAtMs
|
|
654
|
-
).toISOString(),
|
|
655
|
-
status: report.status,
|
|
656
|
-
...channelName ? { channelName } : {},
|
|
657
|
-
...channelNameRedacted ? { channelNameRedacted: true } : {},
|
|
658
|
-
...conversation.source ? { source: conversation.source } : {}
|
|
659
|
-
};
|
|
660
|
-
});
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
// src/reporting/conversations/details.ts
|
|
664
|
-
async function currentRunContent(args) {
|
|
665
|
-
const steps = await args.stepStore.loadCurrentEpoch(args.conversationId);
|
|
666
|
-
const messages = projectSteps(steps).messages;
|
|
667
|
-
const transcript = messages.length > 0 ? messages.map((message) => normalizeTranscriptMessage(message)) : (await args.messageStore.list(args.conversationId)).map(
|
|
668
|
-
visibleMessageTranscript
|
|
669
|
-
);
|
|
670
|
-
return {
|
|
671
|
-
activity: buildConversationActivityFromSteps({
|
|
672
|
-
canExposePayload: args.canExposePayload,
|
|
673
|
-
steps,
|
|
674
|
-
messages
|
|
675
|
-
}),
|
|
676
|
-
transcript
|
|
677
|
-
};
|
|
678
|
-
}
|
|
679
|
-
function visibleMessageTranscript(message) {
|
|
680
|
-
return {
|
|
681
|
-
role: message.role,
|
|
682
|
-
timestamp: message.createdAtMs,
|
|
683
|
-
parts: [{ type: "text", text: message.text }]
|
|
684
|
-
};
|
|
685
|
-
}
|
|
686
|
-
async function readConversationReport(conversationId, options = {}) {
|
|
687
|
-
const store = conversationStore(options);
|
|
688
|
-
const nowMs = Date.now();
|
|
689
|
-
const conversation = await store.get({ conversationId });
|
|
690
|
-
const turnSummaries = conversation ? await listAgentTurnSessionSummariesForConversation(conversationId) : [];
|
|
691
|
-
const currentTurnSummary = conversation ? turnSummaries.find(
|
|
692
|
-
(summary) => summary.sessionId === conversation.execution.runId
|
|
693
|
-
) : void 0;
|
|
694
|
-
const stepStore = getAgentStepStore();
|
|
695
|
-
const messageStore = options.messageStore ?? getConversationMessageStore();
|
|
696
|
-
const transcriptPurgedAtMs = conversation?.transcriptPurgedAtMs;
|
|
697
|
-
const transcriptExpiredAt = transcriptPurgedAtMs !== void 0 ? new Date(transcriptPurgedAtMs).toISOString() : void 0;
|
|
698
|
-
const canExposeSqlContent = conversation !== void 0 && canExposeConversationPayload({
|
|
699
|
-
conversationId,
|
|
700
|
-
visibility: conversation.visibility
|
|
701
|
-
});
|
|
702
|
-
const currentContent = conversation && transcriptPurgedAtMs === void 0 ? await currentRunContent({
|
|
703
|
-
conversationId,
|
|
704
|
-
messageStore,
|
|
705
|
-
stepStore,
|
|
706
|
-
canExposePayload: canExposeSqlContent
|
|
707
|
-
}) : { activity: [], transcript: [] };
|
|
708
|
-
const currentTranscript = currentContent.transcript;
|
|
709
|
-
const traceId = canExposeSqlContent ? traceIdFromTranscript(currentTranscript) : void 0;
|
|
710
|
-
const sentryTraceUrl = traceId ? buildSentryTraceUrl(traceId) : void 0;
|
|
711
|
-
const effectiveRuns = conversation ? [
|
|
712
|
-
{
|
|
713
|
-
...sessionReportFromConversation(conversation, nowMs),
|
|
714
|
-
...currentTurnSummary ? {
|
|
715
|
-
cumulativeDurationMs: currentTurnSummary.cumulativeDurationMs,
|
|
716
|
-
...currentTurnSummary.cumulativeUsage ? { cumulativeUsage: currentTurnSummary.cumulativeUsage } : {}
|
|
717
|
-
} : {},
|
|
718
|
-
...currentTurnSummary?.modelId ? { modelId: currentTurnSummary.modelId } : {},
|
|
719
|
-
...currentTurnSummary?.reasoningLevel ? { reasoningLevel: currentTurnSummary.reasoningLevel } : {},
|
|
720
|
-
...traceId ? { traceId } : {},
|
|
721
|
-
...sentryTraceUrl ? { sentryTraceUrl } : {},
|
|
722
|
-
activity: currentContent.activity,
|
|
723
|
-
transcriptAvailable: transcriptExpiredAt === void 0 && canExposeSqlContent && currentTranscript.length > 0,
|
|
724
|
-
...currentTranscript.length > 0 ? {
|
|
725
|
-
transcriptMessageCount: countConversationMessages(currentTranscript)
|
|
726
|
-
} : {},
|
|
727
|
-
...!canExposeSqlContent && transcriptExpiredAt === void 0 ? {
|
|
728
|
-
transcriptMetadata: currentTranscript.map(
|
|
729
|
-
redactTranscriptMessage
|
|
730
|
-
),
|
|
731
|
-
transcriptRedacted: true,
|
|
732
|
-
transcriptRedactionReason: "non_public_conversation"
|
|
733
|
-
} : {},
|
|
734
|
-
...transcriptExpiredAt !== void 0 ? {
|
|
735
|
-
transcriptExpired: true,
|
|
736
|
-
transcriptExpiredAt,
|
|
737
|
-
transcriptMetadata: []
|
|
738
|
-
} : {},
|
|
739
|
-
transcript: transcriptExpiredAt === void 0 && canExposeSqlContent ? currentTranscript : []
|
|
740
|
-
}
|
|
741
|
-
] : [];
|
|
742
|
-
const firstRun = effectiveRuns[0];
|
|
743
|
-
const displayTitle = firstRun?.displayTitle ?? surfaceFallbackLabel(firstRun?.surface ?? "slack");
|
|
744
|
-
const sentryConversationUrl = buildSentryConversationUrl(conversationId);
|
|
745
|
-
return {
|
|
746
|
-
conversationId,
|
|
747
|
-
displayTitle,
|
|
748
|
-
generatedAt: new Date(nowMs).toISOString(),
|
|
749
|
-
...sentryConversationUrl ? { sentryConversationUrl } : {},
|
|
750
|
-
runs: effectiveRuns
|
|
751
|
-
};
|
|
752
|
-
}
|
|
753
|
-
async function readConversationSubagentTranscriptReport(conversationId, _runId, subagentId, options = {}) {
|
|
754
|
-
const store = conversationStore(options);
|
|
755
|
-
const stepStore = getAgentStepStore();
|
|
756
|
-
const [conversation, parentSteps] = await Promise.all([
|
|
757
|
-
store.get({ conversationId }),
|
|
758
|
-
stepStore.loadHistory(conversationId)
|
|
759
|
-
]);
|
|
760
|
-
if (conversation?.transcriptPurgedAtMs !== void 0) {
|
|
761
|
-
return {
|
|
762
|
-
type: "subagent",
|
|
763
|
-
createdAt: (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
764
|
-
id: subagentId,
|
|
765
|
-
status: "completed",
|
|
766
|
-
subagentKind: "unknown",
|
|
767
|
-
transcript: [],
|
|
768
|
-
transcriptAvailable: false,
|
|
769
|
-
transcriptExpired: true,
|
|
770
|
-
transcriptExpiredAt: new Date(
|
|
771
|
-
conversation.transcriptPurgedAtMs
|
|
772
|
-
).toISOString()
|
|
773
|
-
};
|
|
774
|
-
}
|
|
775
|
-
const start = parentSteps.find(
|
|
776
|
-
(step) => step.entry.type === "subagent_started" && step.entry.subagentInvocationId === subagentId
|
|
777
|
-
);
|
|
778
|
-
if (!start) {
|
|
779
|
-
return {
|
|
780
|
-
type: "subagent",
|
|
781
|
-
createdAt: (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
782
|
-
id: subagentId,
|
|
783
|
-
status: "error",
|
|
784
|
-
subagentKind: "unknown",
|
|
785
|
-
transcript: [],
|
|
786
|
-
transcriptAvailable: false,
|
|
787
|
-
unavailableReason: "not_found"
|
|
788
|
-
};
|
|
789
|
-
}
|
|
790
|
-
const end = parentSteps.find(
|
|
791
|
-
(step) => step.entry.type === "subagent_ended" && step.entry.subagentInvocationId === subagentId
|
|
792
|
-
);
|
|
793
|
-
const childConversationId = start.entry.childConversationId;
|
|
794
|
-
const activity = subagentActivityFromSteps(start, end);
|
|
795
|
-
const subagentSentryConversationUrl = buildSentryConversationUrl(childConversationId);
|
|
796
|
-
const conversationFields = {
|
|
797
|
-
subagentConversationId: childConversationId,
|
|
798
|
-
...subagentSentryConversationUrl ? { subagentSentryConversationUrl } : {}
|
|
799
|
-
};
|
|
800
|
-
const canExposeTranscript = canExposeConversationPayload({
|
|
801
|
-
conversationId,
|
|
802
|
-
visibility: conversation?.visibility
|
|
803
|
-
});
|
|
804
|
-
if (!canExposeTranscript) {
|
|
805
|
-
return subagentTranscriptReport(activity, {
|
|
806
|
-
...conversationFields,
|
|
807
|
-
transcriptRedacted: true,
|
|
808
|
-
transcriptRedactionReason: "non_public_conversation"
|
|
809
|
-
});
|
|
810
|
-
}
|
|
811
|
-
const childMessages = await loadProjection({
|
|
812
|
-
conversationId: childConversationId
|
|
813
|
-
});
|
|
814
|
-
if (childMessages.length === 0) {
|
|
815
|
-
return subagentTranscriptReport(activity, {
|
|
816
|
-
...conversationFields,
|
|
817
|
-
unavailableReason: "missing_transcript_ref"
|
|
818
|
-
});
|
|
819
|
-
}
|
|
820
|
-
const transcript = childMessages.map(
|
|
821
|
-
(message) => normalizeTranscriptMessage(message, {
|
|
822
|
-
unwrapAdvisorTask: activity.subagentKind === "advisor"
|
|
823
|
-
})
|
|
824
|
-
);
|
|
825
|
-
return subagentTranscriptReport(activity, {
|
|
826
|
-
...conversationFields,
|
|
827
|
-
transcript,
|
|
828
|
-
transcriptMessageCount: countConversationMessages(transcript)
|
|
829
|
-
});
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
// src/reporting/conversations/statistics.ts
|
|
833
|
-
var CONVERSATION_STATS_LIMIT = 5e3;
|
|
834
|
-
var RECENT_CONVERSATION_STATS_WINDOW_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
835
|
-
function usageTokenTotal(usage) {
|
|
836
|
-
if (!usage) return void 0;
|
|
837
|
-
const components = [
|
|
838
|
-
usage.inputTokens,
|
|
839
|
-
usage.outputTokens,
|
|
840
|
-
usage.cachedInputTokens,
|
|
841
|
-
usage.cacheCreationTokens
|
|
842
|
-
].reduce((sum, value) => {
|
|
843
|
-
const count = typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.floor(value)) : void 0;
|
|
844
|
-
return count === void 0 ? sum : (sum ?? 0) + count;
|
|
845
|
-
}, void 0);
|
|
846
|
-
if (components !== void 0) {
|
|
847
|
-
return components;
|
|
848
|
-
}
|
|
849
|
-
return typeof usage.totalTokens === "number" && Number.isFinite(usage.totalTokens) ? Math.max(0, Math.floor(usage.totalTokens)) : void 0;
|
|
850
|
-
}
|
|
851
|
-
function usageCostTotal(usage) {
|
|
852
|
-
if (!usage?.cost) return void 0;
|
|
853
|
-
if (typeof usage.cost.total === "number" && Number.isFinite(usage.cost.total)) {
|
|
854
|
-
return Math.max(0, usage.cost.total);
|
|
855
|
-
}
|
|
856
|
-
return [
|
|
857
|
-
usage.cost.input,
|
|
858
|
-
usage.cost.output,
|
|
859
|
-
usage.cost.cacheRead,
|
|
860
|
-
usage.cost.cacheWrite
|
|
861
|
-
].reduce((sum, value) => {
|
|
862
|
-
const amount = typeof value === "number" && Number.isFinite(value) ? Math.max(0, value) : void 0;
|
|
863
|
-
return amount === void 0 ? sum : (sum ?? 0) + amount;
|
|
864
|
-
}, void 0);
|
|
865
|
-
}
|
|
866
|
-
function addUsd(left, right) {
|
|
867
|
-
return Math.round(((left ?? 0) + right) * 1e12) / 1e12;
|
|
868
|
-
}
|
|
869
|
-
function runDurationSnapshot(run) {
|
|
870
|
-
return typeof run.cumulativeDurationMs === "number" && Number.isFinite(run.cumulativeDurationMs) ? Math.max(0, Math.floor(run.cumulativeDurationMs)) : void 0;
|
|
871
|
-
}
|
|
872
|
-
function runContributions(runs) {
|
|
873
|
-
return runs.map((run) => {
|
|
874
|
-
const duration = runDurationSnapshot(run);
|
|
875
|
-
const tokens = usageTokenTotal(run.cumulativeUsage);
|
|
876
|
-
const costUsd = usageCostTotal(run.cumulativeUsage);
|
|
877
|
-
const contribution = {
|
|
878
|
-
durationMs: duration ?? 0,
|
|
879
|
-
run
|
|
880
|
-
};
|
|
881
|
-
if (tokens !== void 0) {
|
|
882
|
-
contribution.tokens = tokens;
|
|
883
|
-
}
|
|
884
|
-
if (costUsd !== void 0) {
|
|
885
|
-
contribution.costUsd = costUsd;
|
|
886
|
-
}
|
|
887
|
-
return contribution;
|
|
888
|
-
});
|
|
889
|
-
}
|
|
890
|
-
function contributionDurationTotal(contributions) {
|
|
891
|
-
return contributions.reduce(
|
|
892
|
-
(sum, contribution) => sum + contribution.durationMs,
|
|
893
|
-
0
|
|
894
|
-
);
|
|
895
|
-
}
|
|
896
|
-
function addTokenTotal(total, tokens) {
|
|
897
|
-
return tokens === void 0 ? total : (total ?? 0) + tokens;
|
|
898
|
-
}
|
|
899
|
-
function contributionTokenTotal(contributions) {
|
|
900
|
-
return contributions.reduce(
|
|
901
|
-
(sum, contribution) => addTokenTotal(sum, contribution.tokens),
|
|
902
|
-
void 0
|
|
903
|
-
);
|
|
904
|
-
}
|
|
905
|
-
function contributionCostTotal(contributions) {
|
|
906
|
-
return contributions.reduce(
|
|
907
|
-
(sum, contribution) => contribution.costUsd === void 0 ? sum : addUsd(sum, contribution.costUsd),
|
|
908
|
-
void 0
|
|
909
|
-
);
|
|
910
|
-
}
|
|
911
|
-
function actorLabel(actor) {
|
|
912
|
-
const email = actor?.email?.trim() || void 0;
|
|
913
|
-
const fullName = actor?.fullName?.trim() || void 0;
|
|
914
|
-
const slackUserName = actor?.slackUserName?.trim() || void 0;
|
|
915
|
-
return email ?? fullName ?? slackUserName ?? actor?.slackUserId;
|
|
916
|
-
}
|
|
917
|
-
function locationLabel(run) {
|
|
918
|
-
return slackStatsLocationLabel(run) ?? surfaceFallbackLabel(run.surface);
|
|
919
|
-
}
|
|
920
|
-
function emptyStatsItem(label) {
|
|
921
|
-
return {
|
|
922
|
-
active: 0,
|
|
923
|
-
conversations: 0,
|
|
924
|
-
durationMs: 0,
|
|
925
|
-
failed: 0,
|
|
926
|
-
hung: 0,
|
|
927
|
-
label,
|
|
928
|
-
runs: 0
|
|
929
|
-
};
|
|
930
|
-
}
|
|
931
|
-
function addItemTokens(item, tokens) {
|
|
932
|
-
if (tokens !== void 0) {
|
|
933
|
-
item.tokens = (item.tokens ?? 0) + tokens;
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
function addItemCost(item, costUsd) {
|
|
937
|
-
if (costUsd !== void 0) {
|
|
938
|
-
item.costUsd = addUsd(item.costUsd, costUsd);
|
|
939
|
-
}
|
|
940
|
-
}
|
|
941
|
-
function statusSignals(runs) {
|
|
942
|
-
return {
|
|
943
|
-
active: runs.some((run) => run.status === "active"),
|
|
944
|
-
failed: runs.some((run) => run.status === "failed"),
|
|
945
|
-
hung: runs.some((run) => run.status === "hung")
|
|
946
|
-
};
|
|
947
|
-
}
|
|
948
|
-
function statsItems(map) {
|
|
949
|
-
return [...map.values()].sort(
|
|
950
|
-
(left, right) => right.conversations - left.conversations || right.runs - left.runs || right.durationMs - left.durationMs || left.label.localeCompare(right.label)
|
|
951
|
-
);
|
|
952
|
-
}
|
|
953
|
-
function recentConversationGroups(args) {
|
|
954
|
-
const startMs = args.nowMs - RECENT_CONVERSATION_STATS_WINDOW_MS;
|
|
955
|
-
const groups = /* @__PURE__ */ new Map();
|
|
956
|
-
for (const summary of args.summaries) {
|
|
957
|
-
groups.set(summary.conversationId, [
|
|
958
|
-
...groups.get(summary.conversationId) ?? [],
|
|
959
|
-
summary
|
|
960
|
-
]);
|
|
961
|
-
}
|
|
962
|
-
return [...groups.values()].map(
|
|
963
|
-
(runs) => [...runs].sort(
|
|
964
|
-
(left, right) => (reportTime(left.startedAt) ?? 0) - (reportTime(right.startedAt) ?? 0) || left.id.localeCompare(right.id)
|
|
965
|
-
)
|
|
966
|
-
).filter((runs) => {
|
|
967
|
-
const activityAt = reportTime(newestRun(runs).lastSeenAt);
|
|
968
|
-
return activityAt !== void 0 && activityAt >= startMs && activityAt <= args.nowMs;
|
|
969
|
-
});
|
|
970
|
-
}
|
|
971
|
-
function conversationDurationMs(runs) {
|
|
972
|
-
if (!runs.some((run) => runDurationSnapshot(run) !== void 0)) {
|
|
973
|
-
return 0;
|
|
974
|
-
}
|
|
975
|
-
return contributionDurationTotal(runContributions(runs));
|
|
976
|
-
}
|
|
977
|
-
function buildConversationStatsReport(args) {
|
|
978
|
-
const conversations = recentConversationGroups(args);
|
|
979
|
-
const actors = /* @__PURE__ */ new Map();
|
|
980
|
-
const locations = /* @__PURE__ */ new Map();
|
|
981
|
-
let durationMs = 0;
|
|
982
|
-
let costUsd;
|
|
983
|
-
let tokens;
|
|
984
|
-
let active = 0;
|
|
985
|
-
let failed = 0;
|
|
986
|
-
let hung = 0;
|
|
987
|
-
for (const runs of conversations) {
|
|
988
|
-
const contributions = runContributions(runs);
|
|
989
|
-
const conversationSignals = statusSignals(runs);
|
|
990
|
-
const conversationCostUsd = contributionCostTotal(contributions);
|
|
991
|
-
const conversationTokens = contributionTokenTotal(contributions);
|
|
992
|
-
durationMs += contributionDurationTotal(contributions);
|
|
993
|
-
costUsd = conversationCostUsd === void 0 ? costUsd : addUsd(costUsd, conversationCostUsd);
|
|
994
|
-
tokens = addTokenTotal(tokens, conversationTokens);
|
|
995
|
-
active += conversationSignals.active ? 1 : 0;
|
|
996
|
-
failed += conversationSignals.failed ? 1 : 0;
|
|
997
|
-
hung += conversationSignals.hung ? 1 : 0;
|
|
998
|
-
const actorRuns = /* @__PURE__ */ new Map();
|
|
999
|
-
for (const contribution of contributions) {
|
|
1000
|
-
const actor = actorLabel(contribution.run.actorIdentity) ?? "Unknown";
|
|
1001
|
-
actorRuns.set(actor, [...actorRuns.get(actor) ?? [], contribution]);
|
|
1002
|
-
}
|
|
1003
|
-
for (const [actor, actorContributions] of actorRuns) {
|
|
1004
|
-
const item = actors.get(actor) ?? emptyStatsItem(actor);
|
|
1005
|
-
const signals = statusSignals(
|
|
1006
|
-
actorContributions.map((contribution) => contribution.run)
|
|
1007
|
-
);
|
|
1008
|
-
item.conversations += 1;
|
|
1009
|
-
item.runs += actorContributions.length;
|
|
1010
|
-
item.durationMs += contributionDurationTotal(actorContributions);
|
|
1011
|
-
item.active += signals.active ? 1 : 0;
|
|
1012
|
-
item.failed += signals.failed ? 1 : 0;
|
|
1013
|
-
item.hung += signals.hung ? 1 : 0;
|
|
1014
|
-
addItemTokens(item, contributionTokenTotal(actorContributions));
|
|
1015
|
-
addItemCost(item, contributionCostTotal(actorContributions));
|
|
1016
|
-
actors.set(actor, item);
|
|
1017
|
-
}
|
|
1018
|
-
const location = locationLabel(newestRun(runs));
|
|
1019
|
-
const locationItem = locations.get(location) ?? emptyStatsItem(location);
|
|
1020
|
-
locationItem.conversations += 1;
|
|
1021
|
-
locationItem.runs += runs.length;
|
|
1022
|
-
locationItem.durationMs += conversationDurationMs(runs);
|
|
1023
|
-
locationItem.active += conversationSignals.active ? 1 : 0;
|
|
1024
|
-
locationItem.failed += conversationSignals.failed ? 1 : 0;
|
|
1025
|
-
locationItem.hung += conversationSignals.hung ? 1 : 0;
|
|
1026
|
-
addItemTokens(locationItem, conversationTokens);
|
|
1027
|
-
addItemCost(locationItem, conversationCostUsd);
|
|
1028
|
-
locations.set(location, locationItem);
|
|
1029
|
-
}
|
|
1030
|
-
return {
|
|
1031
|
-
active,
|
|
1032
|
-
conversations: conversations.length,
|
|
1033
|
-
durationMs,
|
|
1034
|
-
failed,
|
|
1035
|
-
generatedAt: args.generatedAt,
|
|
1036
|
-
hung,
|
|
1037
|
-
locations: statsItems(locations),
|
|
1038
|
-
actors: statsItems(actors),
|
|
1039
|
-
sampleLimit: args.sampleLimit,
|
|
1040
|
-
sampleSize: args.sampleSize,
|
|
1041
|
-
source: "conversation_index",
|
|
1042
|
-
...costUsd !== void 0 ? { costUsd } : {},
|
|
1043
|
-
...tokens !== void 0 ? { tokens } : {},
|
|
1044
|
-
truncated: args.truncated,
|
|
1045
|
-
runs: conversations.reduce((sum, runs) => sum + runs.length, 0),
|
|
1046
|
-
windowEnd: new Date(args.nowMs).toISOString(),
|
|
1047
|
-
windowStart: new Date(
|
|
1048
|
-
args.nowMs - RECENT_CONVERSATION_STATS_WINDOW_MS
|
|
1049
|
-
).toISOString()
|
|
1050
|
-
};
|
|
1051
|
-
}
|
|
1052
|
-
async function readConversationStatsReport(options = {}) {
|
|
1053
|
-
const store = conversationStore(options);
|
|
1054
|
-
const nowMs = Date.now();
|
|
1055
|
-
const generatedAt = new Date(nowMs).toISOString();
|
|
1056
|
-
const conversations = await store.listByActivity({
|
|
1057
|
-
limit: CONVERSATION_STATS_LIMIT + 1
|
|
1058
|
-
});
|
|
1059
|
-
const truncated = conversations.length > CONVERSATION_STATS_LIMIT;
|
|
1060
|
-
const sampledConversations = conversations.slice(0, CONVERSATION_STATS_LIMIT);
|
|
1061
|
-
const summariesByConversation = await listAgentTurnSessionSummariesForConversations(
|
|
1062
|
-
sampledConversations.map((conversation) => conversation.conversationId)
|
|
1063
|
-
);
|
|
1064
|
-
const summaries = sampledConversations.flatMap((conversation) => {
|
|
1065
|
-
const turnSummaries = summariesByConversation.get(conversation.conversationId) ?? [];
|
|
1066
|
-
return turnSummaries.length > 0 ? turnSummaries.map(
|
|
1067
|
-
(summary) => sessionReportFromTurnSummary(conversation, summary, nowMs)
|
|
1068
|
-
) : [sessionReportFromConversation(conversation, nowMs)];
|
|
1069
|
-
});
|
|
1070
|
-
return buildConversationStatsReport({
|
|
1071
|
-
generatedAt,
|
|
1072
|
-
nowMs,
|
|
1073
|
-
sampleLimit: CONVERSATION_STATS_LIMIT,
|
|
1074
|
-
sampleSize: sampledConversations.length,
|
|
1075
|
-
summaries,
|
|
1076
|
-
truncated
|
|
1077
|
-
});
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
|
-
// src/reporting.ts
|
|
1081
|
-
function readDescriptionText() {
|
|
1082
|
-
try {
|
|
1083
|
-
const raw = readFileSync(
|
|
1084
|
-
path.join(homeDir(), "DESCRIPTION.md"),
|
|
1085
|
-
"utf8"
|
|
1086
|
-
).trim();
|
|
1087
|
-
return raw || void 0;
|
|
1088
|
-
} catch {
|
|
1089
|
-
return void 0;
|
|
1090
|
-
}
|
|
1091
|
-
}
|
|
1092
|
-
async function readHealth() {
|
|
1093
|
-
const res = GET();
|
|
1094
|
-
return await res.json();
|
|
1095
|
-
}
|
|
1096
|
-
async function readSkills() {
|
|
1097
|
-
const skills = await discoverSkills();
|
|
1098
|
-
return skills.map((skill) => ({
|
|
1099
|
-
name: skill.name,
|
|
1100
|
-
pluginProvider: skill.pluginProvider
|
|
1101
|
-
}));
|
|
1102
|
-
}
|
|
1103
|
-
async function readPlugins() {
|
|
1104
|
-
return pluginCatalogRuntime.getProviders().map((plugin) => ({
|
|
1105
|
-
name: plugin.manifest.name
|
|
1106
|
-
}));
|
|
1107
|
-
}
|
|
1108
|
-
function createJuniorReporting() {
|
|
1109
|
-
const conversationStore2 = getConversationStore();
|
|
1110
|
-
const listRecent = (listOptions) => listRecentConversationSummaries({
|
|
1111
|
-
...listOptions,
|
|
1112
|
-
conversationStore: conversationStore2
|
|
1113
|
-
});
|
|
1114
|
-
return {
|
|
1115
|
-
getHealth: readHealth,
|
|
1116
|
-
async getRuntimeInfo() {
|
|
1117
|
-
const [plugins, skills] = await Promise.all([
|
|
1118
|
-
readPlugins(),
|
|
1119
|
-
readSkills()
|
|
1120
|
-
]);
|
|
1121
|
-
return {
|
|
1122
|
-
cwd: process.cwd(),
|
|
1123
|
-
homeDir: homeDir(),
|
|
1124
|
-
descriptionText: readDescriptionText(),
|
|
1125
|
-
providers: plugins.map((plugin) => plugin.name),
|
|
1126
|
-
skills,
|
|
1127
|
-
packagedContent: pluginCatalogRuntime.getPackageContent()
|
|
1128
|
-
};
|
|
1129
|
-
},
|
|
1130
|
-
getPlugins: readPlugins,
|
|
1131
|
-
getSkills: readSkills,
|
|
1132
|
-
listConversations: () => readConversationFeed({ conversationStore: conversationStore2 }),
|
|
1133
|
-
getConversationStats: () => readConversationStatsReport({ conversationStore: conversationStore2 }),
|
|
1134
|
-
listRecentConversations: listRecent,
|
|
1135
|
-
getPluginOperationalReports: async () => {
|
|
1136
|
-
const nowMs = Date.now();
|
|
1137
|
-
return {
|
|
1138
|
-
source: "plugins",
|
|
1139
|
-
generatedAt: new Date(nowMs).toISOString(),
|
|
1140
|
-
reports: await getPluginOperationalReports(nowMs, {
|
|
1141
|
-
listRecent
|
|
1142
|
-
})
|
|
1143
|
-
};
|
|
1144
|
-
},
|
|
1145
|
-
getConversation: (conversationId) => readConversationReport(conversationId, { conversationStore: conversationStore2 }),
|
|
1146
|
-
getConversationSubagentTranscript: (conversationId, runId, subagentId) => readConversationSubagentTranscriptReport(
|
|
1147
|
-
conversationId,
|
|
1148
|
-
runId,
|
|
1149
|
-
subagentId
|
|
1150
|
-
)
|
|
1151
|
-
};
|
|
1152
|
-
}
|
|
1153
|
-
export {
|
|
1154
|
-
createJuniorReporting
|
|
1155
|
-
};
|