@sentry/junior 0.71.3 → 0.73.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/bin/junior.mjs +22 -10
- package/dist/api-reference.d.ts +2 -0
- package/dist/app.d.ts +12 -3
- package/dist/app.js +2522 -15560
- package/dist/chat/agent-dispatch/heartbeat.d.ts +0 -6
- package/dist/chat/agent-dispatch/runner.d.ts +2 -0
- package/dist/chat/agent-dispatch/store.d.ts +2 -2
- package/dist/chat/agent-dispatch/types.d.ts +6 -3
- package/dist/chat/agent-dispatch/validation.d.ts +2 -3
- package/dist/chat/app/production.d.ts +8 -1
- package/dist/chat/app/services.d.ts +7 -0
- package/dist/chat/destination.d.ts +3 -1
- package/dist/chat/logging.d.ts +3 -0
- package/dist/chat/mcp/errors.d.ts +3 -0
- package/dist/chat/mcp/tool-manager.d.ts +5 -1
- package/dist/chat/oauth-flow.d.ts +1 -1
- package/dist/chat/plugins/agent-hooks.d.ts +3 -2
- package/dist/chat/plugins/registry.d.ts +2 -0
- package/dist/chat/plugins/types.d.ts +2 -0
- package/dist/chat/prompt.d.ts +4 -1
- package/dist/chat/requester.d.ts +67 -0
- package/dist/chat/respond.d.ts +8 -8
- package/dist/chat/runtime/agent-continue-runner.d.ts +25 -0
- package/dist/chat/runtime/reply-executor.d.ts +7 -5
- package/dist/chat/runtime/slack-resume.d.ts +3 -3
- package/dist/chat/runtime/slack-runtime.d.ts +13 -3
- package/dist/chat/runtime/turn.d.ts +17 -3
- package/dist/chat/sandbox/egress-credentials.d.ts +5 -2
- package/dist/chat/sandbox/egress-policy.d.ts +5 -1
- package/dist/chat/sandbox/egress-proxy.d.ts +2 -0
- package/dist/chat/sandbox/egress-schemas.d.ts +4 -0
- package/dist/chat/sandbox/egress-session.d.ts +3 -1
- package/dist/chat/sandbox/egress-tracing.d.ts +7 -0
- package/dist/chat/sandbox/sandbox.d.ts +2 -0
- package/dist/chat/sandbox/session.d.ts +3 -2
- package/dist/chat/services/agent-continue.d.ts +27 -0
- package/dist/chat/services/auth-pause-response.d.ts +1 -1
- package/dist/chat/services/auth-pause.d.ts +2 -1
- package/dist/chat/services/mcp-auth-orchestration.d.ts +1 -1
- package/dist/chat/services/message-actor-identity.d.ts +12 -4
- package/dist/chat/services/plugin-auth-orchestration.d.ts +9 -8
- package/dist/chat/services/turn-result.d.ts +3 -0
- package/dist/chat/services/turn-session-record.d.ts +10 -7
- package/dist/chat/slack/user.d.ts +4 -4
- package/dist/chat/state/adapter.d.ts +2 -0
- package/dist/chat/state/conversation-details.d.ts +4 -3
- package/dist/chat/state/session-log.d.ts +43 -0
- package/dist/chat/state/turn-session.d.ts +7 -10
- package/dist/chat/task-execution/slack-work.d.ts +5 -5
- package/dist/chat/task-execution/store.d.ts +83 -48
- package/dist/chat/task-execution/worker.d.ts +3 -3
- package/dist/chat/tools/definition.d.ts +3 -0
- package/dist/chat/tools/execution/tool-error-handler.d.ts +2 -1
- package/dist/chat/tools/slack/canvas-tools.d.ts +3 -2
- package/dist/chat/tools/slack/channel-list-messages.d.ts +2 -2
- package/dist/chat/tools/slack/channel-post-message.d.ts +3 -2
- package/dist/chat/tools/slack/context.d.ts +15 -2
- package/dist/chat/tools/slack/message-add-reaction.d.ts +3 -2
- package/dist/chat/tools/slack/thread-read.d.ts +2 -2
- package/dist/chat/tools/types.d.ts +20 -23
- package/dist/{chunk-BBXYXOJW.js → chunk-3BYAPS6B.js} +48 -529
- package/dist/{chunk-UXG6TU2U.js → chunk-7Q5YOUUT.js} +16 -93
- package/dist/chunk-AL5T52ZD.js +1119 -0
- package/dist/chunk-CYUI7JU5.js +195 -0
- package/dist/{chunk-R62YWUNO.js → chunk-DIMX5F3T.js} +10 -28
- package/dist/chunk-G3E7SCME.js +28 -0
- package/dist/chunk-KVZL5NZS.js +519 -0
- package/dist/chunk-M4FLLXXD.js +212 -0
- package/dist/chunk-OQSYYOLM.js +12787 -0
- package/dist/{chunk-GT67ZWZQ.js → chunk-OR6NQJ5E.js} +5 -3
- package/dist/{chunk-B5HKWWQB.js → chunk-RY6AL5C7.js} +8 -6
- package/dist/chunk-SJHUF3DP.js +43 -0
- package/dist/{chunk-XE2VFQQN.js → chunk-UOTZ3EEQ.js} +1 -1
- package/dist/{chunk-HOGQL2H6.js → chunk-UZVHXZ7V.js} +1357 -1486
- package/dist/{chunk-76YMBKW7.js → chunk-V4VYUY4A.js} +27 -14
- package/dist/{chunk-JS4HURDT.js → chunk-WS2EG3GW.js} +224 -224
- package/dist/chunk-ZDA2HYX5.js +275 -0
- package/dist/cli/chat.js +205 -0
- package/dist/cli/check.js +6 -5
- package/dist/cli/run.js +18 -2
- package/dist/cli/snapshot-warmup.js +11 -8
- package/dist/cli/upgrade.js +599 -0
- package/dist/deployment.d.ts +4 -0
- package/dist/handlers/agent-dispatch.d.ts +6 -1
- package/dist/handlers/mcp-oauth-callback.d.ts +6 -1
- package/dist/handlers/oauth-callback.d.ts +6 -1
- package/dist/handlers/sandbox-egress-proxy.d.ts +2 -0
- package/dist/handlers/webhooks.d.ts +4 -2
- package/dist/instrumentation.js +17 -2
- package/dist/nitro.d.ts +1 -1
- package/dist/nitro.js +10 -10
- package/dist/plugins.d.ts +1 -1
- package/dist/reporting/conversations.d.ts +116 -0
- package/dist/reporting.d.ts +24 -129
- package/dist/reporting.js +320 -166
- package/dist/runner-LMAM4OGD.js +259 -0
- package/package.json +3 -3
- package/dist/chat/runtime/timeout-resume-runner.d.ts +0 -19
- package/dist/chat/services/requester-identity.d.ts +0 -19
- package/dist/chat/services/timeout-resume.d.ts +0 -23
- package/dist/chunk-6YY4Q3D4.js +0 -12
- package/dist/chunk-Z3YD6NHK.js +0 -12
- package/dist/handlers/turn-resume.d.ts +0 -4
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getSlackBotToken
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-WS2EG3GW.js";
|
|
4
4
|
import {
|
|
5
|
+
isSlackConversationId,
|
|
6
|
+
isSlackTeamId,
|
|
5
7
|
logWarn
|
|
6
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-3BYAPS6B.js";
|
|
7
9
|
|
|
8
10
|
// src/chat/slack/client.ts
|
|
9
11
|
import { WebClient } from "@slack/web-api";
|
|
@@ -275,17 +277,9 @@ async function downloadPrivateSlackFile(url) {
|
|
|
275
277
|
}
|
|
276
278
|
|
|
277
279
|
// src/chat/destination.ts
|
|
278
|
-
import {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
function isSlackTeamId(value) {
|
|
282
|
-
return /^T[A-Z0-9]+$/.test(value);
|
|
283
|
-
}
|
|
284
|
-
function isSlackConversationId(value) {
|
|
285
|
-
return /^(C|G|D)[A-Z0-9]+$/.test(value);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// src/chat/destination.ts
|
|
280
|
+
import {
|
|
281
|
+
destinationSchema
|
|
282
|
+
} from "@sentry/junior-plugin-api";
|
|
289
283
|
function createSlackDestination(input) {
|
|
290
284
|
const channelId = normalizeSlackConversationId(input.channelId);
|
|
291
285
|
const teamId = input.teamId?.trim();
|
|
@@ -301,10 +295,28 @@ function parseDestination(value) {
|
|
|
301
295
|
const parsed = destinationSchema.safeParse(value);
|
|
302
296
|
return parsed.success ? parsed.data : void 0;
|
|
303
297
|
}
|
|
298
|
+
function requireSlackDestination(destination, action) {
|
|
299
|
+
if (destination?.platform === "slack") {
|
|
300
|
+
return destination;
|
|
301
|
+
}
|
|
302
|
+
throw new Error(`${action} requires a Slack destination`);
|
|
303
|
+
}
|
|
304
304
|
function sameDestination(left, right) {
|
|
305
|
-
|
|
305
|
+
if (left.platform !== right.platform) {
|
|
306
|
+
return false;
|
|
307
|
+
}
|
|
308
|
+
if (left.platform === "local" && right.platform === "local") {
|
|
309
|
+
return left.conversationId === right.conversationId;
|
|
310
|
+
}
|
|
311
|
+
if (left.platform === "slack" && right.platform === "slack") {
|
|
312
|
+
return left.teamId === right.teamId && left.channelId === right.channelId;
|
|
313
|
+
}
|
|
314
|
+
return false;
|
|
306
315
|
}
|
|
307
316
|
function destinationKey(destination) {
|
|
317
|
+
if (destination.platform === "local") {
|
|
318
|
+
return destination.conversationId;
|
|
319
|
+
}
|
|
308
320
|
return `slack:${destination.teamId}:${destination.channelId}`;
|
|
309
321
|
}
|
|
310
322
|
|
|
@@ -321,6 +333,7 @@ export {
|
|
|
321
333
|
downloadPrivateSlackFile,
|
|
322
334
|
createSlackDestination,
|
|
323
335
|
parseDestination,
|
|
336
|
+
requireSlackDestination,
|
|
324
337
|
sameDestination,
|
|
325
338
|
destinationKey
|
|
326
339
|
};
|
|
@@ -6,230 +6,7 @@ import {
|
|
|
6
6
|
setSpanAttributes,
|
|
7
7
|
toOptionalString,
|
|
8
8
|
withSpan
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
|
|
11
|
-
// src/chat/slack/context.ts
|
|
12
|
-
function toTrimmedSlackString(value) {
|
|
13
|
-
const normalized = toOptionalString(value);
|
|
14
|
-
return normalized?.trim() || void 0;
|
|
15
|
-
}
|
|
16
|
-
function parseSlackThreadId(threadId) {
|
|
17
|
-
const normalizedThreadId = toTrimmedSlackString(threadId);
|
|
18
|
-
if (!normalizedThreadId) {
|
|
19
|
-
return void 0;
|
|
20
|
-
}
|
|
21
|
-
const parts = normalizedThreadId.split(":");
|
|
22
|
-
if (parts.length !== 3 || parts[0] !== "slack") {
|
|
23
|
-
return void 0;
|
|
24
|
-
}
|
|
25
|
-
const channelId = toTrimmedSlackString(parts[1]);
|
|
26
|
-
const threadTs = toTrimmedSlackString(parts[2]);
|
|
27
|
-
if (!channelId || !threadTs) {
|
|
28
|
-
return void 0;
|
|
29
|
-
}
|
|
30
|
-
return { channelId, threadTs };
|
|
31
|
-
}
|
|
32
|
-
function resolveSlackChannelIdFromThreadId(threadId) {
|
|
33
|
-
return parseSlackThreadId(threadId)?.channelId;
|
|
34
|
-
}
|
|
35
|
-
function resolveSlackChannelIdFromMessage(message) {
|
|
36
|
-
const messageChannelId = toTrimmedSlackString(
|
|
37
|
-
message.channelId
|
|
38
|
-
);
|
|
39
|
-
if (messageChannelId) {
|
|
40
|
-
return messageChannelId;
|
|
41
|
-
}
|
|
42
|
-
const raw = message.raw;
|
|
43
|
-
if (raw && typeof raw === "object") {
|
|
44
|
-
const rawChannel = toTrimmedSlackString(
|
|
45
|
-
raw.channel
|
|
46
|
-
);
|
|
47
|
-
if (rawChannel) {
|
|
48
|
-
return rawChannel;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
const threadId = toTrimmedSlackString(
|
|
52
|
-
message.threadId
|
|
53
|
-
);
|
|
54
|
-
return resolveSlackChannelIdFromThreadId(threadId);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// src/chat/conversation-privacy.ts
|
|
58
|
-
var SAFE_METADATA_KEY_LIMIT = 20;
|
|
59
|
-
function conversationPrivacyFromChannelId(channelId) {
|
|
60
|
-
const normalized = channelId?.trim();
|
|
61
|
-
if (!normalized) return void 0;
|
|
62
|
-
return normalized.startsWith("C") ? "public" : "private";
|
|
63
|
-
}
|
|
64
|
-
function conversationPrivacyFromConversationId(conversationId) {
|
|
65
|
-
if (!conversationId?.trim()) return void 0;
|
|
66
|
-
const slackThread = parseSlackThreadId(conversationId);
|
|
67
|
-
if (slackThread) {
|
|
68
|
-
return conversationPrivacyFromChannelId(slackThread.channelId);
|
|
69
|
-
}
|
|
70
|
-
return "private";
|
|
71
|
-
}
|
|
72
|
-
function resolveConversationPrivacy(input) {
|
|
73
|
-
return conversationPrivacyFromChannelId(input.channelId) ?? conversationPrivacyFromConversationId(input.conversationId);
|
|
74
|
-
}
|
|
75
|
-
function canExposeConversationPayload(input) {
|
|
76
|
-
return resolveConversationPrivacy(input) === "public";
|
|
77
|
-
}
|
|
78
|
-
function contentMetadata(content) {
|
|
79
|
-
if (typeof content === "string") {
|
|
80
|
-
return [{ type: "text", chars: content.length }];
|
|
81
|
-
}
|
|
82
|
-
if (!Array.isArray(content)) {
|
|
83
|
-
return { type: typeof content };
|
|
84
|
-
}
|
|
85
|
-
return content.map((part) => {
|
|
86
|
-
if (!part || typeof part !== "object") {
|
|
87
|
-
return { type: typeof part };
|
|
88
|
-
}
|
|
89
|
-
const record = part;
|
|
90
|
-
const type = typeof record.type === "string" ? record.type : "unknown";
|
|
91
|
-
return {
|
|
92
|
-
type,
|
|
93
|
-
...typeof record.text === "string" ? { chars: record.text.length } : {},
|
|
94
|
-
...typeof record.mimeType === "string" ? { mimeType: record.mimeType } : {},
|
|
95
|
-
...typeof record.mediaType === "string" ? { mediaType: record.mediaType } : {},
|
|
96
|
-
...typeof record.data === "string" ? { dataChars: record.data.length } : {}
|
|
97
|
-
};
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
function toGenAiMessageMetadata(message) {
|
|
101
|
-
const record = message && typeof message === "object" ? message : {};
|
|
102
|
-
return {
|
|
103
|
-
role: record.role,
|
|
104
|
-
content: contentMetadata(record.content)
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
function toGenAiTextMetadata(text) {
|
|
108
|
-
return { type: "text", chars: text.length };
|
|
109
|
-
}
|
|
110
|
-
function payloadType(payload) {
|
|
111
|
-
return Array.isArray(payload) ? "array" : typeof payload;
|
|
112
|
-
}
|
|
113
|
-
function payloadKeys(payload) {
|
|
114
|
-
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
115
|
-
return void 0;
|
|
116
|
-
}
|
|
117
|
-
const keys = Object.keys(payload).slice(
|
|
118
|
-
0,
|
|
119
|
-
SAFE_METADATA_KEY_LIMIT
|
|
120
|
-
);
|
|
121
|
-
return keys.length > 0 ? keys : void 0;
|
|
122
|
-
}
|
|
123
|
-
function serializedLength(payload) {
|
|
124
|
-
const serialized = typeof payload === "string" ? payload : JSON.stringify(payload);
|
|
125
|
-
return serialized?.length ?? 0;
|
|
126
|
-
}
|
|
127
|
-
function toGenAiPayloadMetadata(payload) {
|
|
128
|
-
const base = {
|
|
129
|
-
type: payloadType(payload),
|
|
130
|
-
chars: serializedLength(payload)
|
|
131
|
-
};
|
|
132
|
-
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
133
|
-
return base;
|
|
134
|
-
}
|
|
135
|
-
const keys = payloadKeys(payload);
|
|
136
|
-
return {
|
|
137
|
-
...base,
|
|
138
|
-
...keys ? { keys } : {}
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
function toGenAiPayloadTraceAttributes(prefix, payload) {
|
|
142
|
-
const attributes = {
|
|
143
|
-
[`${prefix}.type`]: payloadType(payload),
|
|
144
|
-
[`${prefix}.size_chars`]: serializedLength(payload)
|
|
145
|
-
};
|
|
146
|
-
const keys = payloadKeys(payload);
|
|
147
|
-
if (keys) {
|
|
148
|
-
attributes[`${prefix}.keys`] = keys;
|
|
149
|
-
}
|
|
150
|
-
return attributes;
|
|
151
|
-
}
|
|
152
|
-
function summarizeContent(content) {
|
|
153
|
-
if (typeof content === "string") {
|
|
154
|
-
return { chars: content.length, partTypes: ["text"] };
|
|
155
|
-
}
|
|
156
|
-
if (!Array.isArray(content)) {
|
|
157
|
-
return {
|
|
158
|
-
chars: serializedLength(content),
|
|
159
|
-
partTypes: [payloadType(content)]
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
let chars = 0;
|
|
163
|
-
const partTypes = /* @__PURE__ */ new Set();
|
|
164
|
-
for (const part of content) {
|
|
165
|
-
if (!part || typeof part !== "object") {
|
|
166
|
-
chars += serializedLength(part);
|
|
167
|
-
partTypes.add(payloadType(part));
|
|
168
|
-
continue;
|
|
169
|
-
}
|
|
170
|
-
const record = part;
|
|
171
|
-
const type = typeof record.type === "string" ? record.type : "unknown";
|
|
172
|
-
partTypes.add(type);
|
|
173
|
-
if (typeof record.text === "string") {
|
|
174
|
-
chars += record.text.length;
|
|
175
|
-
} else if (typeof record.data === "string") {
|
|
176
|
-
chars += record.data.length;
|
|
177
|
-
} else {
|
|
178
|
-
chars += serializedLength(part);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
return { chars, partTypes: [...partTypes] };
|
|
182
|
-
}
|
|
183
|
-
function toGenAiMessagesTraceAttributes(prefix, messages) {
|
|
184
|
-
let contentChars = 0;
|
|
185
|
-
const roles = /* @__PURE__ */ new Set();
|
|
186
|
-
const partTypes = /* @__PURE__ */ new Set();
|
|
187
|
-
for (const message of messages) {
|
|
188
|
-
if (!message || typeof message !== "object") {
|
|
189
|
-
contentChars += serializedLength(message);
|
|
190
|
-
continue;
|
|
191
|
-
}
|
|
192
|
-
const record = message;
|
|
193
|
-
if (typeof record.role === "string") {
|
|
194
|
-
roles.add(record.role);
|
|
195
|
-
}
|
|
196
|
-
const summary = summarizeContent(record.content);
|
|
197
|
-
contentChars += summary.chars;
|
|
198
|
-
for (const partType of summary.partTypes) {
|
|
199
|
-
partTypes.add(partType);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
return {
|
|
203
|
-
[`${prefix}.message_count`]: messages.length,
|
|
204
|
-
[`${prefix}.content_chars`]: contentChars,
|
|
205
|
-
...roles.size > 0 ? { [`${prefix}.roles`]: [...roles] } : {},
|
|
206
|
-
...partTypes.size > 0 ? { [`${prefix}.part_types`]: [...partTypes] } : {}
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// src/chat/config.ts
|
|
211
|
-
import { getModel } from "@earendil-works/pi-ai";
|
|
212
|
-
|
|
213
|
-
// src/chat/optional-string.ts
|
|
214
|
-
function toOptionalTrimmed(value) {
|
|
215
|
-
if (!value) {
|
|
216
|
-
return void 0;
|
|
217
|
-
}
|
|
218
|
-
const trimmed = value.trim();
|
|
219
|
-
return trimmed.length > 0 ? trimmed : void 0;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// src/chat/pi/client.ts
|
|
223
|
-
import {
|
|
224
|
-
completeSimple,
|
|
225
|
-
getEnvApiKey,
|
|
226
|
-
getModels,
|
|
227
|
-
registerApiProvider
|
|
228
|
-
} from "@earendil-works/pi-ai";
|
|
229
|
-
import {
|
|
230
|
-
streamAnthropic,
|
|
231
|
-
streamSimpleAnthropic
|
|
232
|
-
} from "@earendil-works/pi-ai/anthropic";
|
|
9
|
+
} from "./chunk-3BYAPS6B.js";
|
|
233
10
|
|
|
234
11
|
// src/chat/turn-context-tag.ts
|
|
235
12
|
var TURN_CONTEXT_TAG = "runtime-turn-context";
|
|
@@ -491,6 +268,229 @@ function trimTrailingAssistantMessages(messages) {
|
|
|
491
268
|
return end === messages.length ? [...messages] : messages.slice(0, end);
|
|
492
269
|
}
|
|
493
270
|
|
|
271
|
+
// src/chat/config.ts
|
|
272
|
+
import { getModel } from "@earendil-works/pi-ai";
|
|
273
|
+
|
|
274
|
+
// src/chat/optional-string.ts
|
|
275
|
+
function toOptionalTrimmed(value) {
|
|
276
|
+
if (!value) {
|
|
277
|
+
return void 0;
|
|
278
|
+
}
|
|
279
|
+
const trimmed = value.trim();
|
|
280
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// src/chat/pi/client.ts
|
|
284
|
+
import {
|
|
285
|
+
completeSimple,
|
|
286
|
+
getEnvApiKey,
|
|
287
|
+
getModels,
|
|
288
|
+
registerApiProvider
|
|
289
|
+
} from "@earendil-works/pi-ai";
|
|
290
|
+
import {
|
|
291
|
+
streamAnthropic,
|
|
292
|
+
streamSimpleAnthropic
|
|
293
|
+
} from "@earendil-works/pi-ai/anthropic";
|
|
294
|
+
|
|
295
|
+
// src/chat/slack/context.ts
|
|
296
|
+
function toTrimmedSlackString(value) {
|
|
297
|
+
const normalized = toOptionalString(value);
|
|
298
|
+
return normalized?.trim() || void 0;
|
|
299
|
+
}
|
|
300
|
+
function parseSlackThreadId(threadId) {
|
|
301
|
+
const normalizedThreadId = toTrimmedSlackString(threadId);
|
|
302
|
+
if (!normalizedThreadId) {
|
|
303
|
+
return void 0;
|
|
304
|
+
}
|
|
305
|
+
const parts = normalizedThreadId.split(":");
|
|
306
|
+
if (parts.length !== 3 || parts[0] !== "slack") {
|
|
307
|
+
return void 0;
|
|
308
|
+
}
|
|
309
|
+
const channelId = toTrimmedSlackString(parts[1]);
|
|
310
|
+
const threadTs = toTrimmedSlackString(parts[2]);
|
|
311
|
+
if (!channelId || !threadTs) {
|
|
312
|
+
return void 0;
|
|
313
|
+
}
|
|
314
|
+
return { channelId, threadTs };
|
|
315
|
+
}
|
|
316
|
+
function resolveSlackChannelIdFromThreadId(threadId) {
|
|
317
|
+
return parseSlackThreadId(threadId)?.channelId;
|
|
318
|
+
}
|
|
319
|
+
function resolveSlackChannelIdFromMessage(message) {
|
|
320
|
+
const messageChannelId = toTrimmedSlackString(
|
|
321
|
+
message.channelId
|
|
322
|
+
);
|
|
323
|
+
if (messageChannelId) {
|
|
324
|
+
return messageChannelId;
|
|
325
|
+
}
|
|
326
|
+
const raw = message.raw;
|
|
327
|
+
if (raw && typeof raw === "object") {
|
|
328
|
+
const rawChannel = toTrimmedSlackString(
|
|
329
|
+
raw.channel
|
|
330
|
+
);
|
|
331
|
+
if (rawChannel) {
|
|
332
|
+
return rawChannel;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
const threadId = toTrimmedSlackString(
|
|
336
|
+
message.threadId
|
|
337
|
+
);
|
|
338
|
+
return resolveSlackChannelIdFromThreadId(threadId);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// src/chat/conversation-privacy.ts
|
|
342
|
+
var SAFE_METADATA_KEY_LIMIT = 20;
|
|
343
|
+
function conversationPrivacyFromChannelId(channelId) {
|
|
344
|
+
const normalized = channelId?.trim();
|
|
345
|
+
if (!normalized) return void 0;
|
|
346
|
+
return normalized.startsWith("C") ? "public" : "private";
|
|
347
|
+
}
|
|
348
|
+
function conversationPrivacyFromConversationId(conversationId) {
|
|
349
|
+
if (!conversationId?.trim()) return void 0;
|
|
350
|
+
const slackThread = parseSlackThreadId(conversationId);
|
|
351
|
+
if (slackThread) {
|
|
352
|
+
return conversationPrivacyFromChannelId(slackThread.channelId);
|
|
353
|
+
}
|
|
354
|
+
return "private";
|
|
355
|
+
}
|
|
356
|
+
function resolveConversationPrivacy(input) {
|
|
357
|
+
return conversationPrivacyFromChannelId(input.channelId) ?? conversationPrivacyFromConversationId(input.conversationId);
|
|
358
|
+
}
|
|
359
|
+
function canExposeConversationPayload(input) {
|
|
360
|
+
return resolveConversationPrivacy(input) === "public";
|
|
361
|
+
}
|
|
362
|
+
function contentMetadata(content) {
|
|
363
|
+
if (typeof content === "string") {
|
|
364
|
+
return [{ type: "text", chars: content.length }];
|
|
365
|
+
}
|
|
366
|
+
if (!Array.isArray(content)) {
|
|
367
|
+
return { type: typeof content };
|
|
368
|
+
}
|
|
369
|
+
return content.map((part) => {
|
|
370
|
+
if (!part || typeof part !== "object") {
|
|
371
|
+
return { type: typeof part };
|
|
372
|
+
}
|
|
373
|
+
const record = part;
|
|
374
|
+
const type = typeof record.type === "string" ? record.type : "unknown";
|
|
375
|
+
return {
|
|
376
|
+
type,
|
|
377
|
+
...typeof record.text === "string" ? { chars: record.text.length } : {},
|
|
378
|
+
...typeof record.mimeType === "string" ? { mimeType: record.mimeType } : {},
|
|
379
|
+
...typeof record.mediaType === "string" ? { mediaType: record.mediaType } : {},
|
|
380
|
+
...typeof record.data === "string" ? { dataChars: record.data.length } : {}
|
|
381
|
+
};
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
function toGenAiMessageMetadata(message) {
|
|
385
|
+
const record = message && typeof message === "object" ? message : {};
|
|
386
|
+
return {
|
|
387
|
+
role: record.role,
|
|
388
|
+
content: contentMetadata(record.content)
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
function toGenAiTextMetadata(text) {
|
|
392
|
+
return { type: "text", chars: text.length };
|
|
393
|
+
}
|
|
394
|
+
function payloadType(payload) {
|
|
395
|
+
return Array.isArray(payload) ? "array" : typeof payload;
|
|
396
|
+
}
|
|
397
|
+
function payloadKeys(payload) {
|
|
398
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
399
|
+
return void 0;
|
|
400
|
+
}
|
|
401
|
+
const keys = Object.keys(payload).slice(
|
|
402
|
+
0,
|
|
403
|
+
SAFE_METADATA_KEY_LIMIT
|
|
404
|
+
);
|
|
405
|
+
return keys.length > 0 ? keys : void 0;
|
|
406
|
+
}
|
|
407
|
+
function serializedLength(payload) {
|
|
408
|
+
const serialized = typeof payload === "string" ? payload : JSON.stringify(payload);
|
|
409
|
+
return serialized?.length ?? 0;
|
|
410
|
+
}
|
|
411
|
+
function toGenAiPayloadMetadata(payload) {
|
|
412
|
+
const base = {
|
|
413
|
+
type: payloadType(payload),
|
|
414
|
+
chars: serializedLength(payload)
|
|
415
|
+
};
|
|
416
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
417
|
+
return base;
|
|
418
|
+
}
|
|
419
|
+
const keys = payloadKeys(payload);
|
|
420
|
+
return {
|
|
421
|
+
...base,
|
|
422
|
+
...keys ? { keys } : {}
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
function toGenAiPayloadTraceAttributes(prefix, payload) {
|
|
426
|
+
const attributes = {
|
|
427
|
+
[`${prefix}.type`]: payloadType(payload),
|
|
428
|
+
[`${prefix}.size_chars`]: serializedLength(payload)
|
|
429
|
+
};
|
|
430
|
+
const keys = payloadKeys(payload);
|
|
431
|
+
if (keys) {
|
|
432
|
+
attributes[`${prefix}.keys`] = keys;
|
|
433
|
+
}
|
|
434
|
+
return attributes;
|
|
435
|
+
}
|
|
436
|
+
function summarizeContent(content) {
|
|
437
|
+
if (typeof content === "string") {
|
|
438
|
+
return { chars: content.length, partTypes: ["text"] };
|
|
439
|
+
}
|
|
440
|
+
if (!Array.isArray(content)) {
|
|
441
|
+
return {
|
|
442
|
+
chars: serializedLength(content),
|
|
443
|
+
partTypes: [payloadType(content)]
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
let chars = 0;
|
|
447
|
+
const partTypes = /* @__PURE__ */ new Set();
|
|
448
|
+
for (const part of content) {
|
|
449
|
+
if (!part || typeof part !== "object") {
|
|
450
|
+
chars += serializedLength(part);
|
|
451
|
+
partTypes.add(payloadType(part));
|
|
452
|
+
continue;
|
|
453
|
+
}
|
|
454
|
+
const record = part;
|
|
455
|
+
const type = typeof record.type === "string" ? record.type : "unknown";
|
|
456
|
+
partTypes.add(type);
|
|
457
|
+
if (typeof record.text === "string") {
|
|
458
|
+
chars += record.text.length;
|
|
459
|
+
} else if (typeof record.data === "string") {
|
|
460
|
+
chars += record.data.length;
|
|
461
|
+
} else {
|
|
462
|
+
chars += serializedLength(part);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
return { chars, partTypes: [...partTypes] };
|
|
466
|
+
}
|
|
467
|
+
function toGenAiMessagesTraceAttributes(prefix, messages) {
|
|
468
|
+
let contentChars = 0;
|
|
469
|
+
const roles = /* @__PURE__ */ new Set();
|
|
470
|
+
const partTypes = /* @__PURE__ */ new Set();
|
|
471
|
+
for (const message of messages) {
|
|
472
|
+
if (!message || typeof message !== "object") {
|
|
473
|
+
contentChars += serializedLength(message);
|
|
474
|
+
continue;
|
|
475
|
+
}
|
|
476
|
+
const record = message;
|
|
477
|
+
if (typeof record.role === "string") {
|
|
478
|
+
roles.add(record.role);
|
|
479
|
+
}
|
|
480
|
+
const summary = summarizeContent(record.content);
|
|
481
|
+
contentChars += summary.chars;
|
|
482
|
+
for (const partType of summary.partTypes) {
|
|
483
|
+
partTypes.add(partType);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
return {
|
|
487
|
+
[`${prefix}.message_count`]: messages.length,
|
|
488
|
+
[`${prefix}.content_chars`]: contentChars,
|
|
489
|
+
...roles.size > 0 ? { [`${prefix}.roles`]: [...roles] } : {},
|
|
490
|
+
...partTypes.size > 0 ? { [`${prefix}.part_types`]: [...partTypes] } : {}
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
|
|
494
494
|
// src/chat/services/provider-retry.ts
|
|
495
495
|
var PROVIDER_RETRY_DELAYS_MS = [2e3, 4e3, 8e3];
|
|
496
496
|
var PROVIDER_ERROR_PREFIX = "AI provider error:";
|