@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
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
import {
|
|
2
|
+
conversationSummaryFromStoredConversation
|
|
3
|
+
} from "./chunk-ON6YKIQ7.js";
|
|
4
|
+
import {
|
|
5
|
+
buildSentryConversationUrl,
|
|
6
|
+
buildSentryTraceUrl
|
|
7
|
+
} from "./chunk-LVUKF5CE.js";
|
|
8
|
+
import {
|
|
9
|
+
loadProjection,
|
|
10
|
+
projectSteps
|
|
11
|
+
} from "./chunk-GUAP3H7O.js";
|
|
12
|
+
import {
|
|
13
|
+
getAgentStepStore,
|
|
14
|
+
getConversationMessageStore
|
|
15
|
+
} from "./chunk-35BNLDOJ.js";
|
|
16
|
+
import {
|
|
17
|
+
unescapeXml,
|
|
18
|
+
unwrapCurrentInstruction
|
|
19
|
+
} from "./chunk-EEZCY5WX.js";
|
|
20
|
+
import {
|
|
21
|
+
canExposeConversationPayload
|
|
22
|
+
} from "./chunk-LVA4I4H7.js";
|
|
23
|
+
import {
|
|
24
|
+
isRecord
|
|
25
|
+
} from "./chunk-OB42YVAE.js";
|
|
26
|
+
|
|
27
|
+
// src/api/conversations/transcript.ts
|
|
28
|
+
var SAFE_METADATA_KEY_LIMIT = 20;
|
|
29
|
+
var LEGACY_ADVISOR_TASK_OPEN = "<advisor-task>\n";
|
|
30
|
+
var LEGACY_ADVISOR_TASK_CLOSE = "\n</advisor-task>";
|
|
31
|
+
var LEGACY_EXECUTOR_CONTEXT_OPEN = "<executor-context>\n";
|
|
32
|
+
var LEGACY_EXECUTOR_CONTEXT_CLOSE = "\n</executor-context>";
|
|
33
|
+
function unwrapLegacyAdvisorTask(text) {
|
|
34
|
+
if (!text.startsWith(LEGACY_ADVISOR_TASK_OPEN) || !text.endsWith(LEGACY_EXECUTOR_CONTEXT_CLOSE)) {
|
|
35
|
+
return void 0;
|
|
36
|
+
}
|
|
37
|
+
const taskEnd = text.indexOf(
|
|
38
|
+
LEGACY_ADVISOR_TASK_CLOSE,
|
|
39
|
+
LEGACY_ADVISOR_TASK_OPEN.length
|
|
40
|
+
);
|
|
41
|
+
if (taskEnd < 0) return void 0;
|
|
42
|
+
const contextStart = taskEnd + LEGACY_ADVISOR_TASK_CLOSE.length + 2;
|
|
43
|
+
if (!text.startsWith(LEGACY_EXECUTOR_CONTEXT_OPEN, contextStart)) {
|
|
44
|
+
return void 0;
|
|
45
|
+
}
|
|
46
|
+
const task = text.slice(LEGACY_ADVISOR_TASK_OPEN.length, taskEnd);
|
|
47
|
+
const context = text.slice(
|
|
48
|
+
contextStart + LEGACY_EXECUTOR_CONTEXT_OPEN.length,
|
|
49
|
+
-LEGACY_EXECUTOR_CONTEXT_CLOSE.length
|
|
50
|
+
);
|
|
51
|
+
return `${unescapeXml(task)}
|
|
52
|
+
|
|
53
|
+
Executor context:
|
|
54
|
+
${unescapeXml(context)}`;
|
|
55
|
+
}
|
|
56
|
+
function textPart(text) {
|
|
57
|
+
return { type: "text", text };
|
|
58
|
+
}
|
|
59
|
+
function recordField(value, names) {
|
|
60
|
+
for (const name of names) {
|
|
61
|
+
if (value[name] !== void 0) {
|
|
62
|
+
return value[name];
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return void 0;
|
|
66
|
+
}
|
|
67
|
+
function normalizeTranscriptPart(part, options = {}) {
|
|
68
|
+
const displayText = (text) => {
|
|
69
|
+
if (options.unwrapCurrentTask) {
|
|
70
|
+
const instruction = unwrapCurrentInstruction(text);
|
|
71
|
+
if (instruction !== void 0) return instruction;
|
|
72
|
+
}
|
|
73
|
+
if (options.unwrapLegacyAdvisorTask) {
|
|
74
|
+
return unwrapLegacyAdvisorTask(text) ?? text;
|
|
75
|
+
}
|
|
76
|
+
return text;
|
|
77
|
+
};
|
|
78
|
+
if (typeof part === "string") {
|
|
79
|
+
return textPart(displayText(part));
|
|
80
|
+
}
|
|
81
|
+
if (!isRecord(part)) {
|
|
82
|
+
return { type: "unknown", output: part };
|
|
83
|
+
}
|
|
84
|
+
const rawType = typeof part.type === "string" ? part.type : "unknown";
|
|
85
|
+
if (rawType === "text") {
|
|
86
|
+
const text = recordField(part, ["text", "content"]);
|
|
87
|
+
return textPart(
|
|
88
|
+
typeof text === "string" ? displayText(text) : JSON.stringify(text) ?? ""
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
if (rawType === "toolCall") {
|
|
92
|
+
return {
|
|
93
|
+
type: "tool_call",
|
|
94
|
+
...typeof part.id === "string" ? { id: part.id } : {},
|
|
95
|
+
...typeof part.name === "string" ? { name: part.name } : {},
|
|
96
|
+
input: recordField(part, ["arguments", "input", "args"])
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
if (rawType === "toolResult") {
|
|
100
|
+
return {
|
|
101
|
+
type: "tool_result",
|
|
102
|
+
...typeof part.id === "string" ? { id: part.id } : {},
|
|
103
|
+
...typeof part.name === "string" ? { name: part.name } : {},
|
|
104
|
+
output: recordField(part, ["result", "output", "content"])
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
if (rawType === "thinking") {
|
|
108
|
+
return {
|
|
109
|
+
type: "thinking",
|
|
110
|
+
output: recordField(part, ["thinking", "text", "content", "output"])
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
type: "unknown",
|
|
115
|
+
...rawType !== "unknown" ? { sourceType: rawType } : {},
|
|
116
|
+
output: part
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function normalizeToolResultMessage(record) {
|
|
120
|
+
const content = record.content;
|
|
121
|
+
let output = content;
|
|
122
|
+
if (Array.isArray(content) && content.length === 1 && isRecord(content[0])) {
|
|
123
|
+
const extracted = recordField(content[0], [
|
|
124
|
+
"text",
|
|
125
|
+
"content",
|
|
126
|
+
"output",
|
|
127
|
+
"result"
|
|
128
|
+
]);
|
|
129
|
+
output = extracted !== void 0 ? extracted : content;
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
type: "tool_result",
|
|
133
|
+
...typeof record.toolCallId === "string" ? { id: record.toolCallId } : {},
|
|
134
|
+
...typeof record.name === "string" ? { name: record.name } : typeof record.toolName === "string" ? { name: record.toolName } : {},
|
|
135
|
+
output
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function normalizeTranscriptMessage(message) {
|
|
139
|
+
return normalizeMessage(message);
|
|
140
|
+
}
|
|
141
|
+
function normalizeSubagentTranscriptMessage(message, subagentKind) {
|
|
142
|
+
return normalizeMessage(message, {
|
|
143
|
+
unwrapLegacyAdvisorTask: subagentKind === "advisor"
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
function normalizeMessage(message, options = {}) {
|
|
147
|
+
const record = message;
|
|
148
|
+
const content = record.content;
|
|
149
|
+
const role = transcriptRole(record.role);
|
|
150
|
+
return {
|
|
151
|
+
role,
|
|
152
|
+
...typeof record.timestamp === "number" ? { timestamp: record.timestamp } : {},
|
|
153
|
+
parts: role === "toolResult" ? [normalizeToolResultMessage(record)] : Array.isArray(content) ? content.map(
|
|
154
|
+
(part) => normalizeTranscriptPart(part, {
|
|
155
|
+
unwrapCurrentTask: role === "user",
|
|
156
|
+
unwrapLegacyAdvisorTask: options.unwrapLegacyAdvisorTask && role === "user"
|
|
157
|
+
})
|
|
158
|
+
) : [
|
|
159
|
+
normalizeTranscriptPart(content, {
|
|
160
|
+
unwrapCurrentTask: role === "user",
|
|
161
|
+
unwrapLegacyAdvisorTask: options.unwrapLegacyAdvisorTask && role === "user"
|
|
162
|
+
})
|
|
163
|
+
]
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
function transcriptRole(role) {
|
|
167
|
+
return role === "assistant" || role === "system" || role === "tool" || role === "toolResult" || role === "user" ? role : "unknown";
|
|
168
|
+
}
|
|
169
|
+
function serializedChars(value) {
|
|
170
|
+
if (typeof value === "string") return value.length;
|
|
171
|
+
return JSON.stringify(value)?.length ?? 0;
|
|
172
|
+
}
|
|
173
|
+
function serializedBytes(value) {
|
|
174
|
+
const serialized = typeof value === "string" ? value : JSON.stringify(value);
|
|
175
|
+
return new TextEncoder().encode(serialized ?? "").byteLength;
|
|
176
|
+
}
|
|
177
|
+
function payloadType(value) {
|
|
178
|
+
return Array.isArray(value) ? "array" : typeof value;
|
|
179
|
+
}
|
|
180
|
+
function payloadKeys(value) {
|
|
181
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
182
|
+
return void 0;
|
|
183
|
+
}
|
|
184
|
+
const keys = Object.keys(value).slice(
|
|
185
|
+
0,
|
|
186
|
+
SAFE_METADATA_KEY_LIMIT
|
|
187
|
+
);
|
|
188
|
+
return keys.length > 0 ? keys : void 0;
|
|
189
|
+
}
|
|
190
|
+
function redactedPayloadFields(prefix, value) {
|
|
191
|
+
const keys = payloadKeys(value);
|
|
192
|
+
return {
|
|
193
|
+
[`${prefix}Type`]: payloadType(value),
|
|
194
|
+
[`${prefix}SizeBytes`]: serializedBytes(value),
|
|
195
|
+
[`${prefix}SizeChars`]: serializedChars(value),
|
|
196
|
+
...keys ? { [`${prefix}Keys`]: keys } : {}
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function redactTranscriptPart(part) {
|
|
200
|
+
if (part.type === "text") {
|
|
201
|
+
return {
|
|
202
|
+
type: "text",
|
|
203
|
+
redacted: true,
|
|
204
|
+
bytes: serializedBytes(part.text ?? ""),
|
|
205
|
+
chars: serializedChars(part.text ?? "")
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
if (part.type === "thinking") {
|
|
209
|
+
return {
|
|
210
|
+
type: "thinking",
|
|
211
|
+
redacted: true,
|
|
212
|
+
...redactedPayloadFields("output", part.output)
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
if (part.type === "tool_call") {
|
|
216
|
+
return {
|
|
217
|
+
type: "tool_call",
|
|
218
|
+
redacted: true,
|
|
219
|
+
...part.id ? { id: part.id } : {},
|
|
220
|
+
...part.name ? { name: part.name } : {},
|
|
221
|
+
...redactedPayloadFields("input", part.input)
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
if (part.type === "tool_result") {
|
|
225
|
+
return {
|
|
226
|
+
type: "tool_result",
|
|
227
|
+
redacted: true,
|
|
228
|
+
...part.id ? { id: part.id } : {},
|
|
229
|
+
...part.name ? { name: part.name } : {},
|
|
230
|
+
...redactedPayloadFields("output", part.output)
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
return {
|
|
234
|
+
type: "unknown",
|
|
235
|
+
redacted: true,
|
|
236
|
+
...part.sourceType ? { sourceType: part.sourceType } : {},
|
|
237
|
+
...redactedPayloadFields("output", part.output ?? part.input ?? part.text)
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
function redactTranscriptMessage(message) {
|
|
241
|
+
return {
|
|
242
|
+
role: message.role,
|
|
243
|
+
...typeof message.timestamp === "number" ? { timestamp: message.timestamp } : {},
|
|
244
|
+
parts: message.parts.map(redactTranscriptPart)
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
function isConversationMessageRole(role) {
|
|
248
|
+
return role === "user" || role === "assistant";
|
|
249
|
+
}
|
|
250
|
+
function hasTextPart(message) {
|
|
251
|
+
return message.parts.some((part) => {
|
|
252
|
+
if (part.type !== "text") return false;
|
|
253
|
+
if (part.redacted) return true;
|
|
254
|
+
return typeof part.text === "string" && part.text.trim().length > 0;
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
function isConversationMessage(message) {
|
|
258
|
+
if (!isConversationMessageRole(message.role)) return false;
|
|
259
|
+
if (message.role === "assistant") return hasTextPart(message);
|
|
260
|
+
return message.parts.length > 0;
|
|
261
|
+
}
|
|
262
|
+
function countConversationMessages(transcript) {
|
|
263
|
+
return transcript.filter(isConversationMessage).length;
|
|
264
|
+
}
|
|
265
|
+
function traceIdFromTranscript(transcript) {
|
|
266
|
+
for (const message of transcript) {
|
|
267
|
+
for (const part of message.parts) {
|
|
268
|
+
const text = part.text ?? (typeof part.output === "string" ? part.output : typeof part.input === "string" ? part.input : void 0);
|
|
269
|
+
const match = text?.match(
|
|
270
|
+
/\btrace[_-]?id["']?\s*[:=]\s*["']?([a-f0-9]{16,32})\b/i
|
|
271
|
+
);
|
|
272
|
+
if (match?.[1]) {
|
|
273
|
+
return match[1];
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return void 0;
|
|
278
|
+
}
|
|
279
|
+
function subagentTranscriptReport(activity, options = {}) {
|
|
280
|
+
return {
|
|
281
|
+
type: "subagent",
|
|
282
|
+
...options.subagentConversationId ? { subagentConversationId: options.subagentConversationId } : {},
|
|
283
|
+
createdAt: activity.createdAt,
|
|
284
|
+
id: activity.id,
|
|
285
|
+
...activity.modelId ? { modelId: activity.modelId } : {},
|
|
286
|
+
status: activity.status,
|
|
287
|
+
...options.subagentSentryConversationUrl ? { subagentSentryConversationUrl: options.subagentSentryConversationUrl } : {},
|
|
288
|
+
subagentKind: activity.subagentKind,
|
|
289
|
+
transcript: options.transcript ?? [],
|
|
290
|
+
transcriptAvailable: Boolean(options.transcript?.length),
|
|
291
|
+
...activity.endedAt ? { endedAt: activity.endedAt } : {},
|
|
292
|
+
...activity.outcome ? { outcome: activity.outcome } : {},
|
|
293
|
+
...activity.parentToolCallId ? { parentToolCallId: activity.parentToolCallId } : {},
|
|
294
|
+
...activity.reasoningLevel ? { reasoningLevel: activity.reasoningLevel } : {},
|
|
295
|
+
...options.transcriptMessageCount !== void 0 ? { transcriptMessageCount: options.transcriptMessageCount } : {},
|
|
296
|
+
...options.transcriptRedacted ? { transcriptRedacted: options.transcriptRedacted } : {},
|
|
297
|
+
...options.transcriptRedactionReason ? { transcriptRedactionReason: options.transcriptRedactionReason } : {},
|
|
298
|
+
...options.transcriptExpired ? { transcriptExpired: options.transcriptExpired } : {},
|
|
299
|
+
...options.transcriptExpiredAt ? { transcriptExpiredAt: options.transcriptExpiredAt } : {},
|
|
300
|
+
...options.unavailableReason ? { unavailableReason: options.unavailableReason } : {}
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// src/api/conversations/activity.ts
|
|
305
|
+
function toolResultStatuses(messages) {
|
|
306
|
+
const statuses = /* @__PURE__ */ new Map();
|
|
307
|
+
for (const message of messages) {
|
|
308
|
+
const record = message;
|
|
309
|
+
if (record.role !== "toolResult" || typeof record.toolCallId !== "string") {
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
statuses.set(record.toolCallId, record.isError ? "error" : "completed");
|
|
313
|
+
}
|
|
314
|
+
return statuses;
|
|
315
|
+
}
|
|
316
|
+
function activityPayloadFields(args, canExposePayload) {
|
|
317
|
+
if (args === void 0) {
|
|
318
|
+
return {};
|
|
319
|
+
}
|
|
320
|
+
return canExposePayload ? { args } : { redacted: true, ...redactedPayloadFields("input", args) };
|
|
321
|
+
}
|
|
322
|
+
function buildConversationActivityFromSteps(args) {
|
|
323
|
+
const toolStatuses = toolResultStatuses(args.messages);
|
|
324
|
+
const subagentEnds = /* @__PURE__ */ new Map();
|
|
325
|
+
const subagentsByToolCallId = /* @__PURE__ */ new Map();
|
|
326
|
+
const orphanSubagents = [];
|
|
327
|
+
for (const step of args.steps) {
|
|
328
|
+
if (step.entry.type === "subagent_ended") {
|
|
329
|
+
subagentEnds.set(
|
|
330
|
+
step.entry.subagentInvocationId,
|
|
331
|
+
step
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
for (const step of args.steps) {
|
|
336
|
+
if (step.entry.type !== "subagent_started") {
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
const start = step;
|
|
340
|
+
const parentStatus = start.entry.parentToolCallId ? toolStatuses.get(start.entry.parentToolCallId) : void 0;
|
|
341
|
+
const activity = subagentActivityFromSteps(
|
|
342
|
+
start,
|
|
343
|
+
subagentEnds.get(start.entry.subagentInvocationId),
|
|
344
|
+
{ canExposeTranscript: args.canExposePayload, parentStatus }
|
|
345
|
+
);
|
|
346
|
+
if (start.entry.parentToolCallId) {
|
|
347
|
+
subagentsByToolCallId.set(start.entry.parentToolCallId, [
|
|
348
|
+
...subagentsByToolCallId.get(start.entry.parentToolCallId) ?? [],
|
|
349
|
+
activity
|
|
350
|
+
]);
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
orphanSubagents.push(activity);
|
|
354
|
+
}
|
|
355
|
+
const rows = [];
|
|
356
|
+
for (const step of args.steps) {
|
|
357
|
+
if (step.entry.type !== "tool_execution_started") {
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
rows.push({
|
|
361
|
+
type: "tool_execution",
|
|
362
|
+
id: step.entry.toolCallId,
|
|
363
|
+
toolCallId: step.entry.toolCallId,
|
|
364
|
+
toolName: step.entry.toolName,
|
|
365
|
+
createdAt: new Date(step.createdAtMs).toISOString(),
|
|
366
|
+
status: toolStatuses.get(step.entry.toolCallId) ?? "running",
|
|
367
|
+
subagents: subagentsByToolCallId.get(step.entry.toolCallId) ?? [],
|
|
368
|
+
...activityPayloadFields(step.entry.args, args.canExposePayload)
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
return [...rows, ...orphanSubagents].sort(
|
|
372
|
+
(left, right) => Date.parse(left.createdAt) - Date.parse(right.createdAt) || left.id.localeCompare(right.id)
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
function subagentActivityFromSteps(start, end, options = {}) {
|
|
376
|
+
return {
|
|
377
|
+
type: "subagent",
|
|
378
|
+
id: start.entry.subagentInvocationId,
|
|
379
|
+
subagentKind: start.entry.subagentKind,
|
|
380
|
+
...start.entry.modelId ? { modelId: start.entry.modelId } : {},
|
|
381
|
+
...start.entry.parentToolCallId ? { parentToolCallId: start.entry.parentToolCallId } : {},
|
|
382
|
+
...start.entry.reasoningLevel ? { reasoningLevel: start.entry.reasoningLevel } : {},
|
|
383
|
+
createdAt: new Date(start.createdAtMs).toISOString(),
|
|
384
|
+
...end ? {
|
|
385
|
+
endedAt: new Date(end.createdAtMs).toISOString(),
|
|
386
|
+
outcome: end.entry.outcome,
|
|
387
|
+
status: end.entry.outcome,
|
|
388
|
+
// Every subagent is a child conversation whose transcript loads on
|
|
389
|
+
// demand; expose the affordance only when the parent is public.
|
|
390
|
+
...options.canExposeTranscript ? { transcriptAvailable: true } : {}
|
|
391
|
+
} : { status: options.parentStatus ?? "running" }
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// src/api/conversations/detail-projection.ts
|
|
396
|
+
async function currentRunContent(args) {
|
|
397
|
+
const steps = await args.stepStore.loadCurrentEpoch(args.conversationId);
|
|
398
|
+
const messages = projectSteps(steps).messages;
|
|
399
|
+
const transcript = messages.length > 0 ? messages.map((message) => normalizeTranscriptMessage(message)) : (await args.messageStore.list(args.conversationId)).map(
|
|
400
|
+
visibleMessageTranscript
|
|
401
|
+
);
|
|
402
|
+
return {
|
|
403
|
+
activity: buildConversationActivityFromSteps({
|
|
404
|
+
canExposePayload: args.canExposePayload,
|
|
405
|
+
steps,
|
|
406
|
+
messages
|
|
407
|
+
}),
|
|
408
|
+
transcript
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
function visibleMessageTranscript(message) {
|
|
412
|
+
return {
|
|
413
|
+
role: message.role,
|
|
414
|
+
timestamp: message.createdAtMs,
|
|
415
|
+
parts: [{ type: "text", text: message.text }]
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
async function buildConversationDetail(args) {
|
|
419
|
+
const { conversation } = args;
|
|
420
|
+
const conversationId = conversation.conversationId;
|
|
421
|
+
const nowMs = Date.now();
|
|
422
|
+
const stepStore = getAgentStepStore();
|
|
423
|
+
const messageStore = getConversationMessageStore();
|
|
424
|
+
const transcriptPurgedAtMs = conversation.transcriptPurgedAtMs;
|
|
425
|
+
const transcriptExpiredAt = transcriptPurgedAtMs !== void 0 ? new Date(transcriptPurgedAtMs).toISOString() : void 0;
|
|
426
|
+
const canExposeSqlContent = canExposeConversationPayload({
|
|
427
|
+
conversationId,
|
|
428
|
+
visibility: conversation.visibility
|
|
429
|
+
});
|
|
430
|
+
const currentContent = transcriptPurgedAtMs === void 0 ? await currentRunContent({
|
|
431
|
+
conversationId,
|
|
432
|
+
messageStore,
|
|
433
|
+
stepStore,
|
|
434
|
+
canExposePayload: canExposeSqlContent
|
|
435
|
+
}) : { activity: [], transcript: [] };
|
|
436
|
+
const currentTranscript = currentContent.transcript;
|
|
437
|
+
const traceId = canExposeSqlContent ? traceIdFromTranscript(currentTranscript) : void 0;
|
|
438
|
+
const sentryTraceUrl = traceId ? buildSentryTraceUrl(traceId) : void 0;
|
|
439
|
+
const sentryConversationUrl = buildSentryConversationUrl(conversationId);
|
|
440
|
+
return {
|
|
441
|
+
...conversationSummaryFromStoredConversation({
|
|
442
|
+
conversation,
|
|
443
|
+
durationMs: args.durationMs,
|
|
444
|
+
nowMs,
|
|
445
|
+
usage: args.usage
|
|
446
|
+
}),
|
|
447
|
+
...traceId ? { traceId } : {},
|
|
448
|
+
...sentryTraceUrl ? { sentryTraceUrl } : {},
|
|
449
|
+
activity: currentContent.activity,
|
|
450
|
+
transcriptAvailable: transcriptExpiredAt === void 0 && canExposeSqlContent && currentTranscript.length > 0,
|
|
451
|
+
...currentTranscript.length > 0 ? {
|
|
452
|
+
transcriptMessageCount: countConversationMessages(currentTranscript)
|
|
453
|
+
} : {},
|
|
454
|
+
...!canExposeSqlContent && transcriptExpiredAt === void 0 ? {
|
|
455
|
+
transcriptMetadata: currentTranscript.map(redactTranscriptMessage),
|
|
456
|
+
transcriptRedacted: true,
|
|
457
|
+
transcriptRedactionReason: "non_public_conversation"
|
|
458
|
+
} : {},
|
|
459
|
+
...transcriptExpiredAt !== void 0 ? {
|
|
460
|
+
transcriptExpired: true,
|
|
461
|
+
transcriptExpiredAt,
|
|
462
|
+
transcriptMetadata: []
|
|
463
|
+
} : {},
|
|
464
|
+
transcript: transcriptExpiredAt === void 0 && canExposeSqlContent ? currentTranscript : [],
|
|
465
|
+
generatedAt: new Date(nowMs).toISOString(),
|
|
466
|
+
...sentryConversationUrl ? { sentryConversationUrl } : {}
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
async function buildConversationSubagent(conversation, subagentId) {
|
|
470
|
+
const conversationId = conversation.conversationId;
|
|
471
|
+
const stepStore = getAgentStepStore();
|
|
472
|
+
const parentSteps = await stepStore.loadHistory(conversationId);
|
|
473
|
+
if (conversation?.transcriptPurgedAtMs !== void 0) {
|
|
474
|
+
return {
|
|
475
|
+
type: "subagent",
|
|
476
|
+
createdAt: (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
477
|
+
id: subagentId,
|
|
478
|
+
status: "completed",
|
|
479
|
+
subagentKind: "unknown",
|
|
480
|
+
transcript: [],
|
|
481
|
+
transcriptAvailable: false,
|
|
482
|
+
transcriptExpired: true,
|
|
483
|
+
transcriptExpiredAt: new Date(
|
|
484
|
+
conversation.transcriptPurgedAtMs
|
|
485
|
+
).toISOString()
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
const start = parentSteps.find(
|
|
489
|
+
(step) => step.entry.type === "subagent_started" && step.entry.subagentInvocationId === subagentId
|
|
490
|
+
);
|
|
491
|
+
if (!start) {
|
|
492
|
+
return {
|
|
493
|
+
type: "subagent",
|
|
494
|
+
createdAt: (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
495
|
+
id: subagentId,
|
|
496
|
+
status: "error",
|
|
497
|
+
subagentKind: "unknown",
|
|
498
|
+
transcript: [],
|
|
499
|
+
transcriptAvailable: false,
|
|
500
|
+
unavailableReason: "not_found"
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
const end = parentSteps.find(
|
|
504
|
+
(step) => step.entry.type === "subagent_ended" && step.entry.subagentInvocationId === subagentId
|
|
505
|
+
);
|
|
506
|
+
const childConversationId = start.entry.childConversationId;
|
|
507
|
+
const activity = subagentActivityFromSteps(start, end);
|
|
508
|
+
const subagentSentryConversationUrl = buildSentryConversationUrl(childConversationId);
|
|
509
|
+
const conversationFields = {
|
|
510
|
+
subagentConversationId: childConversationId,
|
|
511
|
+
...subagentSentryConversationUrl ? { subagentSentryConversationUrl } : {}
|
|
512
|
+
};
|
|
513
|
+
const canExposeTranscript = canExposeConversationPayload({
|
|
514
|
+
conversationId,
|
|
515
|
+
visibility: conversation?.visibility
|
|
516
|
+
});
|
|
517
|
+
if (!canExposeTranscript) {
|
|
518
|
+
return subagentTranscriptReport(activity, {
|
|
519
|
+
...conversationFields,
|
|
520
|
+
transcriptRedacted: true,
|
|
521
|
+
transcriptRedactionReason: "non_public_conversation"
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
const childMessages = await loadProjection({
|
|
525
|
+
conversationId: childConversationId
|
|
526
|
+
});
|
|
527
|
+
if (childMessages.length === 0) {
|
|
528
|
+
return subagentTranscriptReport(activity, {
|
|
529
|
+
...conversationFields,
|
|
530
|
+
unavailableReason: "missing_transcript_ref"
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
const transcript = childMessages.map(
|
|
534
|
+
(message) => normalizeSubagentTranscriptMessage(message, activity.subagentKind)
|
|
535
|
+
);
|
|
536
|
+
return subagentTranscriptReport(activity, {
|
|
537
|
+
...conversationFields,
|
|
538
|
+
transcript,
|
|
539
|
+
transcriptMessageCount: countConversationMessages(transcript)
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
export {
|
|
544
|
+
buildConversationDetail,
|
|
545
|
+
buildConversationSubagent
|
|
546
|
+
};
|