@sentry/junior 0.72.0 → 0.74.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 +12 -10
- package/dist/api-reference.d.ts +1 -1
- package/dist/app.d.ts +11 -2
- package/dist/app.js +1233 -13143
- 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 +11 -1
- package/dist/chat/app/services.d.ts +7 -0
- package/dist/chat/config.d.ts +3 -0
- package/dist/chat/conversations/configured.d.ts +5 -0
- package/dist/chat/conversations/sql/migrations.d.ts +11 -0
- package/dist/chat/conversations/sql/schema/conversations.d.ts +435 -0
- package/dist/chat/conversations/sql/schema/destinations.d.ts +200 -0
- package/dist/chat/conversations/sql/schema/identities.d.ts +214 -0
- package/dist/chat/conversations/sql/schema/migrations.d.ts +58 -0
- package/dist/chat/conversations/sql/schema/timestamps.d.ts +1 -0
- package/dist/chat/conversations/sql/schema.d.ts +910 -0
- package/dist/chat/conversations/sql/store.d.ts +52 -0
- package/dist/chat/conversations/state.d.ts +4 -0
- package/dist/chat/conversations/store.d.ts +57 -0
- package/dist/chat/destination.d.ts +3 -1
- package/dist/chat/ingress/slack-webhook.d.ts +2 -0
- package/dist/chat/logging.d.ts +3 -0
- package/dist/chat/oauth-flow.d.ts +1 -1
- package/dist/chat/plugins/agent-hooks.d.ts +2 -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 +19 -12
- package/dist/chat/respond.d.ts +7 -3
- package/dist/chat/runtime/agent-continue-runner.d.ts +1 -1
- package/dist/chat/runtime/reply-executor.d.ts +3 -1
- 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 +15 -1
- 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/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 +7 -6
- package/dist/chat/services/message-actor-identity.d.ts +2 -2
- package/dist/chat/services/pending-auth.d.ts +2 -0
- package/dist/chat/services/plugin-auth-orchestration.d.ts +14 -12
- package/dist/chat/services/turn-result.d.ts +3 -0
- package/dist/chat/slack/user.d.ts +2 -2
- package/dist/chat/sql/db.d.ts +20 -0
- package/dist/chat/sql/neon.d.ts +9 -0
- package/dist/chat/sql/schema.d.ts +906 -0
- package/dist/chat/state/turn-session.d.ts +3 -0
- package/dist/chat/task-execution/slack-work.d.ts +2 -0
- package/dist/chat/task-execution/state.d.ts +209 -0
- package/dist/chat/task-execution/store.d.ts +30 -114
- package/dist/chat/task-execution/vercel-callback.d.ts +2 -0
- package/dist/chat/task-execution/worker.d.ts +2 -0
- 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 +19 -19
- package/dist/chunk-2LUZA3LY.js +275 -0
- package/dist/{chunk-6GEYPE6T.js → chunk-3BYAPS6B.js} +30 -6
- package/dist/{chunk-VLIO6RQR.js → chunk-6UP2Z2RZ.js} +4 -4
- package/dist/{chunk-GB3AL54K.js → chunk-7Q5YOUUT.js} +10 -2
- package/dist/{chunk-PP7AGSBU.js → chunk-CYUI7JU5.js} +18 -8
- package/dist/{chunk-3FYPXHPL.js → chunk-F6HWCPOC.js} +1 -1
- package/dist/{chunk-ZJQPA67D.js → chunk-GM7HTXYC.js} +230 -224
- package/dist/{chunk-VSNA5KAB.js → chunk-HYHKTFG2.js} +1338 -1499
- package/dist/chunk-JL2SLRAT.js +1970 -0
- package/dist/{chunk-4JXCSGSA.js → chunk-M4FLLXXD.js} +1 -1
- package/dist/{chunk-55XEZFGD.js → chunk-OR6NQJ5E.js} +2 -2
- package/dist/chunk-SJHUF3DP.js +43 -0
- package/dist/chunk-SQGMG7OD.js +12801 -0
- package/dist/{chunk-QUXPUKBH.js → chunk-Y7X25LFY.js} +1 -1
- package/dist/{chunk-ICKIDP7G.js → chunk-YOHFWWBV.js} +1 -1
- package/dist/{chunk-XC33FJZN.js → chunk-YRDS7VKO.js} +25 -4
- package/dist/cli/chat.js +205 -0
- package/dist/cli/check.js +9 -10
- package/dist/cli/init.js +1 -1
- package/dist/cli/run.js +10 -2
- package/dist/cli/snapshot-warmup.js +7 -7
- package/dist/cli/upgrade.js +81 -11
- 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 -3
- package/dist/nitro.js +9 -10
- package/dist/reporting/conversations.d.ts +13 -3
- package/dist/reporting.d.ts +9 -2
- package/dist/reporting.js +114 -48
- package/dist/runner-27NP2TEO.js +259 -0
- package/dist/vercel.d.ts +6 -1
- package/dist/vercel.js +1 -1
- package/package.json +9 -4
- package/dist/chunk-6YY4Q3D4.js +0 -12
- package/dist/chunk-HNMUVGSR.js +0 -1119
- package/dist/chunk-Z3YD6NHK.js +0 -12
package/dist/reporting.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { PluginOperationalReport } from "@sentry/junior-plugin-api";
|
|
2
|
-
import { type ConversationFeed, type ConversationReport, type ConversationStatsReport } from "./reporting/conversations";
|
|
3
|
-
export type { ConversationFeed, ConversationReport, ConversationReportStatus, ConversationRunReport, ConversationStatsItem, ConversationStatsReport, ConversationSummaryReport, ConversationSurface, ConversationUsage, RequesterIdentity, TranscriptMessage, TranscriptPart, TranscriptPartType, TranscriptRole, } from "./reporting/conversations";
|
|
2
|
+
import { type ConversationFeed, type AgentPluginConversationSummary, type ConversationReport, type ConversationStatsReport } from "./reporting/conversations";
|
|
3
|
+
export type { AgentPluginConversationStatus, AgentPluginConversations, AgentPluginConversationSummary, ConversationFeed, ConversationReport, ConversationReportStatus, ConversationRunReport, ConversationStatsItem, ConversationStatsReport, ConversationSummaryReport, ConversationSurface, ConversationUsage, RequesterIdentity, TranscriptMessage, TranscriptPart, TranscriptPartType, TranscriptRole, } from "./reporting/conversations";
|
|
4
4
|
export interface HealthReport {
|
|
5
5
|
status: "ok";
|
|
6
6
|
service: string;
|
|
@@ -52,6 +52,10 @@ export interface JuniorReporting {
|
|
|
52
52
|
getSessions(): Promise<ConversationFeed>;
|
|
53
53
|
/** Read aggregate conversation stats for reporting consumers. */
|
|
54
54
|
getConversationStats?(): Promise<ConversationStatsReport>;
|
|
55
|
+
/** Read recent conversation summaries without transcript payloads. */
|
|
56
|
+
listRecentConversations?(options?: {
|
|
57
|
+
limit?: number;
|
|
58
|
+
}): Promise<AgentPluginConversationSummary[]>;
|
|
55
59
|
/** Read sanitized operational summaries contributed by plugins. */
|
|
56
60
|
getPluginOperationalReports?(): Promise<PluginOperationalReportFeed>;
|
|
57
61
|
/**
|
|
@@ -66,5 +70,8 @@ export interface JuniorReporting {
|
|
|
66
70
|
/** Create the read-only reporting boundary used by plugins and other consumers. */
|
|
67
71
|
export declare function createJuniorReporting(): JuniorReporting & {
|
|
68
72
|
getConversationStats(): Promise<ConversationStatsReport>;
|
|
73
|
+
listRecentConversations(options?: {
|
|
74
|
+
limit?: number;
|
|
75
|
+
}): Promise<AgentPluginConversationSummary[]>;
|
|
69
76
|
getPluginOperationalReports(): Promise<PluginOperationalReportFeed>;
|
|
70
77
|
};
|
package/dist/reporting.js
CHANGED
|
@@ -2,42 +2,42 @@ import {
|
|
|
2
2
|
GET,
|
|
3
3
|
buildSentryConversationUrl,
|
|
4
4
|
buildSentryTraceUrl,
|
|
5
|
-
buildSystemPrompt,
|
|
6
5
|
formatSlackConversationRedactedLabel,
|
|
7
|
-
getAgentPluginOperationalReports,
|
|
8
|
-
getAgentTurnSessionRecord,
|
|
9
6
|
getConversationDetails,
|
|
10
7
|
getConversationDetailsForIds,
|
|
11
|
-
listAgentTurnSessionSummariesForConversation,
|
|
12
8
|
resolveSlackConversationContextFromThreadId
|
|
13
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-2LUZA3LY.js";
|
|
14
10
|
import {
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
buildSystemPrompt,
|
|
12
|
+
getAgentPluginOperationalReports,
|
|
13
|
+
getAgentTurnSessionRecord,
|
|
14
|
+
getConfiguredConversationStore,
|
|
15
|
+
listAgentTurnSessionSummariesForConversation
|
|
16
|
+
} from "./chunk-HYHKTFG2.js";
|
|
17
17
|
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
import "./chunk-
|
|
18
|
+
discoverSkills
|
|
19
|
+
} from "./chunk-OR6NQJ5E.js";
|
|
20
|
+
import "./chunk-JL2SLRAT.js";
|
|
21
|
+
import "./chunk-YRDS7VKO.js";
|
|
22
22
|
import "./chunk-G3E7SCME.js";
|
|
23
23
|
import {
|
|
24
24
|
getPluginPackageContent,
|
|
25
25
|
getPluginProviders
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-7Q5YOUUT.js";
|
|
27
27
|
import {
|
|
28
28
|
homeDir
|
|
29
29
|
} from "./chunk-KVZL5NZS.js";
|
|
30
|
-
import "./chunk-
|
|
30
|
+
import "./chunk-F6HWCPOC.js";
|
|
31
31
|
import {
|
|
32
32
|
canExposeConversationPayload,
|
|
33
33
|
parseSlackThreadId,
|
|
34
34
|
resolveConversationPrivacy
|
|
35
|
-
} from "./chunk-
|
|
36
|
-
import "./chunk-
|
|
35
|
+
} from "./chunk-GM7HTXYC.js";
|
|
36
|
+
import "./chunk-CYUI7JU5.js";
|
|
37
37
|
import {
|
|
38
38
|
isRecord
|
|
39
|
-
} from "./chunk-
|
|
40
|
-
import "./chunk-
|
|
39
|
+
} from "./chunk-3BYAPS6B.js";
|
|
40
|
+
import "./chunk-SJHUF3DP.js";
|
|
41
41
|
import "./chunk-2KG3PWR4.js";
|
|
42
42
|
|
|
43
43
|
// src/reporting.ts
|
|
@@ -51,6 +51,9 @@ var PRIVATE_CONVERSATION_LABEL = "Private Conversation";
|
|
|
51
51
|
var CONVERSATION_FEED_LIMIT = 50;
|
|
52
52
|
var CONVERSATION_STATS_LIMIT = 5e3;
|
|
53
53
|
var RECENT_CONVERSATION_STATS_WINDOW_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
54
|
+
function conversationStore(options = {}) {
|
|
55
|
+
return options.conversationStore ?? getConfiguredConversationStore();
|
|
56
|
+
}
|
|
54
57
|
function statusFromCheckpoint(summary, nowMs = Date.now()) {
|
|
55
58
|
const state = summary.state;
|
|
56
59
|
if (state === "running" && nowMs - summary.lastProgressAtMs > HUNG_TURN_PROGRESS_MS) {
|
|
@@ -145,10 +148,10 @@ function sessionReportFromSummary(summary, nowMs = Date.now(), details) {
|
|
|
145
148
|
};
|
|
146
149
|
}
|
|
147
150
|
function statusFromConversation(conversation, fallback, nowMs) {
|
|
151
|
+
if (fallback) {
|
|
152
|
+
return fallback;
|
|
153
|
+
}
|
|
148
154
|
if (conversation.execution.status === "idle") {
|
|
149
|
-
if (fallback === "failed" || fallback === "superseded") {
|
|
150
|
-
return fallback;
|
|
151
|
-
}
|
|
152
155
|
return "completed";
|
|
153
156
|
}
|
|
154
157
|
const updatedAtMs = conversation.execution.updatedAtMs ?? conversation.updatedAtMs;
|
|
@@ -172,13 +175,30 @@ function titleFromConversation(args) {
|
|
|
172
175
|
channelName: effectiveChannelName
|
|
173
176
|
}) ?? surfaceFallbackLabel(args.surface);
|
|
174
177
|
}
|
|
178
|
+
function channelNameFromConversation(conversation, details) {
|
|
179
|
+
const effectiveChannelName = details?.channelName ?? conversation.channelName;
|
|
180
|
+
const slackThread = parseSlackThreadId(conversation.conversationId);
|
|
181
|
+
if (!effectiveChannelName && !slackThread) {
|
|
182
|
+
return void 0;
|
|
183
|
+
}
|
|
184
|
+
const slackConversation = resolveSlackConversationContextFromThreadId({
|
|
185
|
+
threadId: conversation.conversationId,
|
|
186
|
+
channelName: effectiveChannelName
|
|
187
|
+
});
|
|
188
|
+
if (resolveConversationPrivacy({
|
|
189
|
+
conversationId: conversation.conversationId
|
|
190
|
+
}) !== "public") {
|
|
191
|
+
return formatSlackConversationRedactedLabel(slackConversation) ?? (slackConversation ? void 0 : PRIVATE_CONVERSATION_LABEL);
|
|
192
|
+
}
|
|
193
|
+
return effectiveChannelName;
|
|
194
|
+
}
|
|
175
195
|
function applyConversationIndexMetadata(args) {
|
|
176
196
|
const surface = args.details?.originSurface ?? (args.conversation.source ? surfaceFromSource(
|
|
177
197
|
args.conversation.source,
|
|
178
198
|
args.conversation.conversationId
|
|
179
199
|
) : args.report.surface);
|
|
180
200
|
const slackThread = parseSlackThreadId(args.conversation.conversationId);
|
|
181
|
-
const effectiveChannelName = args.
|
|
201
|
+
const effectiveChannelName = channelNameFromConversation(args.conversation, args.details) ?? args.report.channelName;
|
|
182
202
|
const requesterIdentity = requesterIdentityReport(args.details?.originRequester) ?? args.report.requesterIdentity ?? requesterIdentityReport(args.conversation.requester);
|
|
183
203
|
const status = statusFromConversation(
|
|
184
204
|
args.conversation,
|
|
@@ -189,10 +209,6 @@ function applyConversationIndexMetadata(args) {
|
|
|
189
209
|
reportTime(args.report.lastSeenAt) ?? 0,
|
|
190
210
|
args.conversation.lastActivityAtMs
|
|
191
211
|
);
|
|
192
|
-
const lastProgressAtMs = Math.max(
|
|
193
|
-
reportTime(args.report.lastProgressAt) ?? 0,
|
|
194
|
-
args.conversation.execution.updatedAtMs ?? args.conversation.updatedAtMs
|
|
195
|
-
);
|
|
196
212
|
return {
|
|
197
213
|
...args.report,
|
|
198
214
|
displayTitle: titleFromConversation({
|
|
@@ -202,7 +218,6 @@ function applyConversationIndexMetadata(args) {
|
|
|
202
218
|
}),
|
|
203
219
|
status,
|
|
204
220
|
lastSeenAt: new Date(lastSeenAtMs).toISOString(),
|
|
205
|
-
lastProgressAt: new Date(lastProgressAtMs).toISOString(),
|
|
206
221
|
surface,
|
|
207
222
|
...requesterIdentity ? { requesterIdentity } : {},
|
|
208
223
|
...slackThread ? { channel: slackThread.channelId } : {},
|
|
@@ -218,6 +233,7 @@ function sessionReportFromConversation(conversation, nowMs, details) {
|
|
|
218
233
|
details?.originRequester ?? conversation.requester
|
|
219
234
|
);
|
|
220
235
|
const slackThread = parseSlackThreadId(conversation.conversationId);
|
|
236
|
+
const channelName = channelNameFromConversation(conversation, details);
|
|
221
237
|
return {
|
|
222
238
|
conversationId: conversation.conversationId,
|
|
223
239
|
cumulativeDurationMs: 0,
|
|
@@ -232,7 +248,7 @@ function sessionReportFromConversation(conversation, nowMs, details) {
|
|
|
232
248
|
surface,
|
|
233
249
|
...requesterIdentity ? { requesterIdentity } : {},
|
|
234
250
|
...slackThread ? { channel: slackThread.channelId } : {},
|
|
235
|
-
...
|
|
251
|
+
...channelName ? { channelName } : {},
|
|
236
252
|
...sentryConversationUrl ? { sentryConversationUrl } : {}
|
|
237
253
|
};
|
|
238
254
|
}
|
|
@@ -655,10 +671,10 @@ function isConversationMessage(message) {
|
|
|
655
671
|
function countConversationMessages(transcript) {
|
|
656
672
|
return transcript.filter(isConversationMessage).length;
|
|
657
673
|
}
|
|
658
|
-
function systemPromptMessage() {
|
|
674
|
+
function systemPromptMessage(destination) {
|
|
659
675
|
return {
|
|
660
676
|
role: "system",
|
|
661
|
-
parts: [{ type: "text", text: buildSystemPrompt() }]
|
|
677
|
+
parts: [{ type: "text", text: buildSystemPrompt({ source: destination }) }]
|
|
662
678
|
};
|
|
663
679
|
}
|
|
664
680
|
function turnScopedMessages(messages, turnStartMessageIndex) {
|
|
@@ -727,9 +743,10 @@ async function reportsFromConversations(args) {
|
|
|
727
743
|
}
|
|
728
744
|
return reports;
|
|
729
745
|
}
|
|
730
|
-
async function readConversationFeed() {
|
|
746
|
+
async function readConversationFeed(options = {}) {
|
|
747
|
+
const store = conversationStore(options);
|
|
731
748
|
const nowMs = Date.now();
|
|
732
|
-
const conversations = await
|
|
749
|
+
const conversations = await store.listByActivity({
|
|
733
750
|
limit: CONVERSATION_FEED_LIMIT
|
|
734
751
|
});
|
|
735
752
|
const detailsByConversationId = await getConversationDetailsForIds(
|
|
@@ -756,10 +773,11 @@ async function readConversationFeed() {
|
|
|
756
773
|
)
|
|
757
774
|
};
|
|
758
775
|
}
|
|
759
|
-
async function readConversationStatsReport() {
|
|
776
|
+
async function readConversationStatsReport(options = {}) {
|
|
777
|
+
const store = conversationStore(options);
|
|
760
778
|
const nowMs = Date.now();
|
|
761
779
|
const generatedAt = new Date(nowMs).toISOString();
|
|
762
|
-
const conversations = await
|
|
780
|
+
const conversations = await store.listByActivity({
|
|
763
781
|
limit: CONVERSATION_STATS_LIMIT + 1
|
|
764
782
|
});
|
|
765
783
|
const truncated = conversations.length > CONVERSATION_STATS_LIMIT;
|
|
@@ -790,12 +808,53 @@ async function readConversationStatsReport() {
|
|
|
790
808
|
truncated
|
|
791
809
|
});
|
|
792
810
|
}
|
|
793
|
-
async function
|
|
811
|
+
async function listRecentConversationSummaries(options = {}) {
|
|
812
|
+
const store = conversationStore(options);
|
|
813
|
+
const nowMs = Date.now();
|
|
814
|
+
const limit = Math.max(0, Math.min(100, Math.floor(options.limit ?? 25)));
|
|
815
|
+
const conversations = await store.listByActivity({
|
|
816
|
+
limit
|
|
817
|
+
});
|
|
818
|
+
const detailsByConversationId = await getConversationDetailsForIds(
|
|
819
|
+
conversations.map((conversation) => conversation.conversationId)
|
|
820
|
+
);
|
|
821
|
+
const reportsByConversation = await reportsFromConversations({
|
|
822
|
+
conversations,
|
|
823
|
+
detailsByConversationId,
|
|
824
|
+
nowMs
|
|
825
|
+
});
|
|
826
|
+
return conversations.map((conversation) => {
|
|
827
|
+
const details = detailsByConversationId.get(conversation.conversationId);
|
|
828
|
+
const surface = surfaceFromSource(
|
|
829
|
+
conversation.source,
|
|
830
|
+
conversation.conversationId
|
|
831
|
+
);
|
|
832
|
+
const channelName = channelNameFromConversation(conversation, details);
|
|
833
|
+
const report = newestRun(
|
|
834
|
+
reportsByConversation.get(conversation.conversationId) ?? [
|
|
835
|
+
sessionReportFromConversation(conversation, nowMs, details)
|
|
836
|
+
]
|
|
837
|
+
);
|
|
838
|
+
return {
|
|
839
|
+
conversationId: conversation.conversationId,
|
|
840
|
+
displayTitle: titleFromConversation({ conversation, details, surface }),
|
|
841
|
+
lastActivityAt: new Date(conversation.lastActivityAtMs).toISOString(),
|
|
842
|
+
lastUpdatedAt: new Date(
|
|
843
|
+
conversation.execution.updatedAtMs ?? conversation.updatedAtMs
|
|
844
|
+
).toISOString(),
|
|
845
|
+
status: report.status,
|
|
846
|
+
...channelName ? { channelName } : {},
|
|
847
|
+
...conversation.source ? { source: conversation.source } : {}
|
|
848
|
+
};
|
|
849
|
+
});
|
|
850
|
+
}
|
|
851
|
+
async function readConversationReport(conversationId, options = {}) {
|
|
852
|
+
const store = conversationStore(options);
|
|
794
853
|
const nowMs = Date.now();
|
|
795
854
|
const [rawSummaries, details, conversation] = await Promise.all([
|
|
796
855
|
listAgentTurnSessionSummariesForConversation(conversationId),
|
|
797
856
|
getConversationDetails(conversationId),
|
|
798
|
-
|
|
857
|
+
store.get({ conversationId })
|
|
799
858
|
]);
|
|
800
859
|
const summaries = rawSummaries.sort(
|
|
801
860
|
(left, right) => left.startedAtMs - right.startedAtMs || left.updatedAtMs - right.updatedAtMs || left.sessionId.localeCompare(right.sessionId)
|
|
@@ -816,7 +875,7 @@ async function readConversationReport(conversationId) {
|
|
|
816
875
|
);
|
|
817
876
|
const transcriptMessageCount = countConversationMessages(normalizedTranscript);
|
|
818
877
|
const transcript = canExposeTranscript ? [
|
|
819
|
-
...scopedMessages.startsAtRunBoundary && normalizedTranscript.length > 0 ? [systemPromptMessage()] : [],
|
|
878
|
+
...scopedMessages.startsAtRunBoundary && normalizedTranscript.length > 0 && sessionRecord?.destination ? [systemPromptMessage(sessionRecord.destination)] : [],
|
|
820
879
|
...normalizedTranscript
|
|
821
880
|
] : [];
|
|
822
881
|
const transcriptMetadata = canExposeTranscript ? void 0 : normalizedTranscript.map(redactTranscriptMessage);
|
|
@@ -891,15 +950,12 @@ async function readPlugins() {
|
|
|
891
950
|
name: plugin.manifest.name
|
|
892
951
|
}));
|
|
893
952
|
}
|
|
894
|
-
async function readPluginOperationalReports() {
|
|
895
|
-
const nowMs = Date.now();
|
|
896
|
-
return {
|
|
897
|
-
source: "plugins",
|
|
898
|
-
generatedAt: new Date(nowMs).toISOString(),
|
|
899
|
-
reports: await getAgentPluginOperationalReports(nowMs)
|
|
900
|
-
};
|
|
901
|
-
}
|
|
902
953
|
function createJuniorReporting() {
|
|
954
|
+
const conversationStore2 = getConfiguredConversationStore();
|
|
955
|
+
const listRecent = (listOptions) => listRecentConversationSummaries({
|
|
956
|
+
...listOptions,
|
|
957
|
+
conversationStore: conversationStore2
|
|
958
|
+
});
|
|
903
959
|
return {
|
|
904
960
|
getHealth: readHealth,
|
|
905
961
|
async getRuntimeInfo() {
|
|
@@ -918,10 +974,20 @@ function createJuniorReporting() {
|
|
|
918
974
|
},
|
|
919
975
|
getPlugins: readPlugins,
|
|
920
976
|
getSkills: readSkills,
|
|
921
|
-
getSessions: readConversationFeed,
|
|
922
|
-
getConversationStats: readConversationStatsReport,
|
|
923
|
-
|
|
924
|
-
|
|
977
|
+
getSessions: () => readConversationFeed({ conversationStore: conversationStore2 }),
|
|
978
|
+
getConversationStats: () => readConversationStatsReport({ conversationStore: conversationStore2 }),
|
|
979
|
+
listRecentConversations: listRecent,
|
|
980
|
+
getPluginOperationalReports: async () => {
|
|
981
|
+
const nowMs = Date.now();
|
|
982
|
+
return {
|
|
983
|
+
source: "plugins",
|
|
984
|
+
generatedAt: new Date(nowMs).toISOString(),
|
|
985
|
+
reports: await getAgentPluginOperationalReports(nowMs, {
|
|
986
|
+
listRecent
|
|
987
|
+
})
|
|
988
|
+
};
|
|
989
|
+
},
|
|
990
|
+
getConversation: (conversationId) => readConversationReport(conversationId, { conversationStore: conversationStore2 })
|
|
925
991
|
};
|
|
926
992
|
}
|
|
927
993
|
export {
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildConversationContext,
|
|
3
|
+
buildDeliveredTurnStatePatch,
|
|
4
|
+
coerceThreadArtifactsState,
|
|
5
|
+
generateAssistantReply,
|
|
6
|
+
getPersistedSandboxState,
|
|
7
|
+
getPersistedThreadState,
|
|
8
|
+
markConversationMessage,
|
|
9
|
+
markTurnFailed,
|
|
10
|
+
normalizeConversationText,
|
|
11
|
+
persistThreadStateById,
|
|
12
|
+
startActiveTurn,
|
|
13
|
+
updateConversationStats,
|
|
14
|
+
upsertConversationMessage
|
|
15
|
+
} from "./chunk-SQGMG7OD.js";
|
|
16
|
+
import {
|
|
17
|
+
commitMessages,
|
|
18
|
+
loadProjection
|
|
19
|
+
} from "./chunk-HYHKTFG2.js";
|
|
20
|
+
import "./chunk-OR6NQJ5E.js";
|
|
21
|
+
import {
|
|
22
|
+
coerceThreadConversationState
|
|
23
|
+
} from "./chunk-M4FLLXXD.js";
|
|
24
|
+
import "./chunk-JL2SLRAT.js";
|
|
25
|
+
import "./chunk-YRDS7VKO.js";
|
|
26
|
+
import "./chunk-6UP2Z2RZ.js";
|
|
27
|
+
import "./chunk-G3E7SCME.js";
|
|
28
|
+
import "./chunk-7Q5YOUUT.js";
|
|
29
|
+
import "./chunk-KVZL5NZS.js";
|
|
30
|
+
import "./chunk-F6HWCPOC.js";
|
|
31
|
+
import {
|
|
32
|
+
stripRuntimeTurnContext,
|
|
33
|
+
trimTrailingAssistantMessages
|
|
34
|
+
} from "./chunk-GM7HTXYC.js";
|
|
35
|
+
import "./chunk-CYUI7JU5.js";
|
|
36
|
+
import "./chunk-3BYAPS6B.js";
|
|
37
|
+
import "./chunk-SJHUF3DP.js";
|
|
38
|
+
import "./chunk-2KG3PWR4.js";
|
|
39
|
+
|
|
40
|
+
// src/chat/local/runner.ts
|
|
41
|
+
import { THREAD_STATE_TTL_MS } from "chat";
|
|
42
|
+
import {
|
|
43
|
+
localDestinationSchema
|
|
44
|
+
} from "@sentry/junior-plugin-api";
|
|
45
|
+
var DELIVERED_STATE_PERSIST_ATTEMPTS = 3;
|
|
46
|
+
function localDestination(conversationId) {
|
|
47
|
+
const parsed = localDestinationSchema.safeParse({
|
|
48
|
+
platform: "local",
|
|
49
|
+
conversationId
|
|
50
|
+
});
|
|
51
|
+
if (!parsed.success) {
|
|
52
|
+
throw new Error("Invalid local conversation id");
|
|
53
|
+
}
|
|
54
|
+
return parsed.data;
|
|
55
|
+
}
|
|
56
|
+
function localTurnId(sequence) {
|
|
57
|
+
return `local-turn-${sequence}`;
|
|
58
|
+
}
|
|
59
|
+
function localReply(reply) {
|
|
60
|
+
return {
|
|
61
|
+
...reply.files ? { files: reply.files } : {},
|
|
62
|
+
text: reply.text
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function sleep(ms) {
|
|
66
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
67
|
+
}
|
|
68
|
+
function nextUserMessageSequence(conversation) {
|
|
69
|
+
return conversation.messages.filter((message) => message.role === "user").length + 1;
|
|
70
|
+
}
|
|
71
|
+
function preparedLocalPiMessages(messages) {
|
|
72
|
+
return stripRuntimeTurnContext(trimTrailingAssistantMessages(messages));
|
|
73
|
+
}
|
|
74
|
+
async function loadLocalPiMessages(args) {
|
|
75
|
+
const projection = await loadProjection({
|
|
76
|
+
conversationId: args.conversationId
|
|
77
|
+
});
|
|
78
|
+
if (args.fallback.length >= projection.length && args.fallback.length > 0) {
|
|
79
|
+
return preparedLocalPiMessages(args.fallback);
|
|
80
|
+
}
|
|
81
|
+
if (projection.length > 0) {
|
|
82
|
+
return preparedLocalPiMessages(projection);
|
|
83
|
+
}
|
|
84
|
+
return void 0;
|
|
85
|
+
}
|
|
86
|
+
async function persistDeliveredLocalTurnState(conversationId, patch) {
|
|
87
|
+
let lastError;
|
|
88
|
+
for (let attempt = 1; attempt <= DELIVERED_STATE_PERSIST_ATTEMPTS; attempt += 1) {
|
|
89
|
+
try {
|
|
90
|
+
await persistThreadStateById(conversationId, patch);
|
|
91
|
+
return;
|
|
92
|
+
} catch (error) {
|
|
93
|
+
lastError = error;
|
|
94
|
+
if (attempt < DELIVERED_STATE_PERSIST_ATTEMPTS) {
|
|
95
|
+
await sleep(attempt * 100);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
throw lastError;
|
|
100
|
+
}
|
|
101
|
+
async function runLocalAgentTurn(input, deps) {
|
|
102
|
+
const text = input.message.trim();
|
|
103
|
+
if (!text) {
|
|
104
|
+
throw new Error("Local agent message must not be empty");
|
|
105
|
+
}
|
|
106
|
+
if (!deps.deliverReply) {
|
|
107
|
+
throw new Error("Local reply delivery is required");
|
|
108
|
+
}
|
|
109
|
+
const destination = localDestination(input.conversationId);
|
|
110
|
+
const generateAssistantReply2 = deps.generateAssistantReply ?? generateAssistantReply;
|
|
111
|
+
const now = deps.now ?? (() => Date.now());
|
|
112
|
+
const persisted = await getPersistedThreadState(input.conversationId);
|
|
113
|
+
const conversation = coerceThreadConversationState(persisted);
|
|
114
|
+
let artifacts = coerceThreadArtifactsState(persisted);
|
|
115
|
+
let { sandboxId, sandboxDependencyProfileHash } = getPersistedSandboxState(persisted);
|
|
116
|
+
const initialArtifacts = artifacts;
|
|
117
|
+
const initialSandboxId = sandboxId;
|
|
118
|
+
const initialSandboxDependencyProfileHash = sandboxDependencyProfileHash;
|
|
119
|
+
const sequence = nextUserMessageSequence(conversation);
|
|
120
|
+
const turnId = localTurnId(sequence);
|
|
121
|
+
const userMessageId = `${turnId}:user`;
|
|
122
|
+
const startedAtMs = now();
|
|
123
|
+
upsertConversationMessage(conversation, {
|
|
124
|
+
id: userMessageId,
|
|
125
|
+
role: "user",
|
|
126
|
+
text: normalizeConversationText(text),
|
|
127
|
+
createdAtMs: startedAtMs,
|
|
128
|
+
author: {
|
|
129
|
+
fullName: "Local CLI",
|
|
130
|
+
userId: "local-cli",
|
|
131
|
+
userName: "local"
|
|
132
|
+
},
|
|
133
|
+
meta: {
|
|
134
|
+
explicitMention: true,
|
|
135
|
+
replied: false
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
startActiveTurn({
|
|
139
|
+
conversation,
|
|
140
|
+
nextTurnId: turnId,
|
|
141
|
+
updateConversationStats
|
|
142
|
+
});
|
|
143
|
+
await persistThreadStateById(input.conversationId, { conversation });
|
|
144
|
+
let reply;
|
|
145
|
+
let completedState;
|
|
146
|
+
let piMessagesBeforeRun;
|
|
147
|
+
try {
|
|
148
|
+
const piMessages = await loadLocalPiMessages({
|
|
149
|
+
conversationId: input.conversationId,
|
|
150
|
+
fallback: conversation.piMessages
|
|
151
|
+
});
|
|
152
|
+
piMessagesBeforeRun = piMessages;
|
|
153
|
+
reply = await generateAssistantReply2(text, {
|
|
154
|
+
authorizationFlowMode: "disabled",
|
|
155
|
+
conversationContext: buildConversationContext(conversation, {
|
|
156
|
+
excludeMessageId: userMessageId
|
|
157
|
+
}),
|
|
158
|
+
artifactState: artifacts,
|
|
159
|
+
credentialContext: {
|
|
160
|
+
actor: { type: "system", id: "local-cli" }
|
|
161
|
+
},
|
|
162
|
+
destination,
|
|
163
|
+
requester: {
|
|
164
|
+
fullName: "Local CLI",
|
|
165
|
+
platform: "local",
|
|
166
|
+
userId: "local-cli",
|
|
167
|
+
userName: "local"
|
|
168
|
+
},
|
|
169
|
+
piMessages,
|
|
170
|
+
surface: "internal",
|
|
171
|
+
correlation: {
|
|
172
|
+
conversationId: input.conversationId,
|
|
173
|
+
turnId,
|
|
174
|
+
runId: turnId
|
|
175
|
+
},
|
|
176
|
+
sandbox: {
|
|
177
|
+
sandboxId,
|
|
178
|
+
sandboxDependencyProfileHash
|
|
179
|
+
},
|
|
180
|
+
onArtifactStateUpdated: async (nextArtifacts) => {
|
|
181
|
+
artifacts = nextArtifacts;
|
|
182
|
+
await persistThreadStateById(input.conversationId, {
|
|
183
|
+
artifacts,
|
|
184
|
+
conversation,
|
|
185
|
+
sandboxId,
|
|
186
|
+
sandboxDependencyProfileHash
|
|
187
|
+
});
|
|
188
|
+
},
|
|
189
|
+
onSandboxAcquired: async (sandbox) => {
|
|
190
|
+
sandboxId = sandbox.sandboxId;
|
|
191
|
+
sandboxDependencyProfileHash = sandbox.sandboxDependencyProfileHash;
|
|
192
|
+
await persistThreadStateById(input.conversationId, {
|
|
193
|
+
artifacts,
|
|
194
|
+
conversation,
|
|
195
|
+
sandboxId,
|
|
196
|
+
sandboxDependencyProfileHash
|
|
197
|
+
});
|
|
198
|
+
},
|
|
199
|
+
onStatus: async (status) => {
|
|
200
|
+
await deps.onStatus?.(status.text);
|
|
201
|
+
},
|
|
202
|
+
onTextDelta: deps.onTextDelta
|
|
203
|
+
});
|
|
204
|
+
completedState = buildDeliveredTurnStatePatch({
|
|
205
|
+
artifacts,
|
|
206
|
+
conversation,
|
|
207
|
+
reply,
|
|
208
|
+
sessionId: turnId,
|
|
209
|
+
userMessageId
|
|
210
|
+
});
|
|
211
|
+
await deps.deliverReply(localReply(reply));
|
|
212
|
+
} catch (error) {
|
|
213
|
+
if (reply) {
|
|
214
|
+
await commitMessages({
|
|
215
|
+
conversationId: input.conversationId,
|
|
216
|
+
messages: piMessagesBeforeRun ?? [],
|
|
217
|
+
ttlMs: THREAD_STATE_TTL_MS
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
markTurnFailed({
|
|
221
|
+
conversation,
|
|
222
|
+
nowMs: now(),
|
|
223
|
+
sessionId: turnId,
|
|
224
|
+
userMessageId,
|
|
225
|
+
markConversationMessage,
|
|
226
|
+
updateConversationStats
|
|
227
|
+
});
|
|
228
|
+
await persistThreadStateById(input.conversationId, {
|
|
229
|
+
artifacts: initialArtifacts,
|
|
230
|
+
conversation,
|
|
231
|
+
sandboxId: initialSandboxId ?? "",
|
|
232
|
+
sandboxDependencyProfileHash: initialSandboxDependencyProfileHash ?? ""
|
|
233
|
+
});
|
|
234
|
+
throw error;
|
|
235
|
+
}
|
|
236
|
+
await persistDeliveredLocalTurnState(input.conversationId, {
|
|
237
|
+
artifacts: completedState.artifacts ?? artifacts,
|
|
238
|
+
conversation: reply.piMessages ? {
|
|
239
|
+
...completedState.conversation,
|
|
240
|
+
piMessages: reply.piMessages
|
|
241
|
+
} : completedState.conversation,
|
|
242
|
+
sandboxId: reply.sandboxId ?? sandboxId,
|
|
243
|
+
sandboxDependencyProfileHash: reply.sandboxDependencyProfileHash ?? sandboxDependencyProfileHash
|
|
244
|
+
});
|
|
245
|
+
if (reply.piMessages) {
|
|
246
|
+
await commitMessages({
|
|
247
|
+
conversationId: input.conversationId,
|
|
248
|
+
messages: reply.piMessages,
|
|
249
|
+
ttlMs: THREAD_STATE_TTL_MS
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
return {
|
|
253
|
+
conversationId: input.conversationId,
|
|
254
|
+
outcome: reply.diagnostics.outcome
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
export {
|
|
258
|
+
runLocalAgentTurn
|
|
259
|
+
};
|
package/dist/vercel.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
export interface JuniorVercelConfigOptions {
|
|
2
|
+
/** Override the Vercel build command, or pass null to omit it. */
|
|
2
3
|
buildCommand?: string | null;
|
|
3
4
|
}
|
|
4
|
-
/** Return the root Vercel project config for scaffolded Junior apps.
|
|
5
|
+
/** Return the root Vercel project config for scaffolded Junior apps.
|
|
6
|
+
*
|
|
7
|
+
* New apps run `junior upgrade` before `pnpm build`; older installs without
|
|
8
|
+
* Junior SQL configured can override `buildCommand` to keep their prior build.
|
|
9
|
+
*/
|
|
5
10
|
export declare function juniorVercelConfig(options?: JuniorVercelConfigOptions): Record<string, unknown>;
|
package/dist/vercel.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/junior",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.74.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
"@earendil-works/pi-agent-core": "0.74.2",
|
|
51
51
|
"@earendil-works/pi-ai": "0.74.2",
|
|
52
52
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
53
|
+
"@neondatabase/serverless": "^1.1.0",
|
|
53
54
|
"@sinclair/typebox": "^0.34.49",
|
|
54
55
|
"@slack/web-api": "^7.16.0",
|
|
55
56
|
"@sentry/node": "10.53.1",
|
|
@@ -59,17 +60,20 @@
|
|
|
59
60
|
"ai": "^6.0.190",
|
|
60
61
|
"bash-tool": "^1.3.16",
|
|
61
62
|
"chat": "4.29.0",
|
|
63
|
+
"drizzle-orm": "^0.45.2",
|
|
62
64
|
"hono": "^4.12.22",
|
|
63
65
|
"jose": "^6.2.3",
|
|
64
66
|
"just-bash": "3.0.1",
|
|
65
67
|
"node-html-markdown": "^2.0.0",
|
|
66
68
|
"yaml": "^2.9.0",
|
|
67
69
|
"zod": "^4.4.3",
|
|
68
|
-
"@sentry/junior-plugin-api": "0.
|
|
70
|
+
"@sentry/junior-plugin-api": "0.74.0"
|
|
69
71
|
},
|
|
70
72
|
"devDependencies": {
|
|
73
|
+
"@emnapi/core": "^1.10.0",
|
|
74
|
+
"@emnapi/runtime": "^1.10.0",
|
|
71
75
|
"@types/node": "^25.9.1",
|
|
72
|
-
"@vitest/coverage-v8": "
|
|
76
|
+
"@vitest/coverage-v8": "4.1.7",
|
|
73
77
|
"dependency-cruiser": "^17.4.0",
|
|
74
78
|
"msw": "^2.14.6",
|
|
75
79
|
"nitro": "3.0.260522-beta",
|
|
@@ -78,7 +82,8 @@
|
|
|
78
82
|
"typescript": "^6.0.3",
|
|
79
83
|
"vercel": "^54.4.0",
|
|
80
84
|
"vitest": "^4.1.7",
|
|
81
|
-
"@sentry/junior-
|
|
85
|
+
"@sentry/junior-test-fixtures": "0.72.0",
|
|
86
|
+
"@sentry/junior-scheduler": "0.74.0"
|
|
82
87
|
},
|
|
83
88
|
"scripts": {
|
|
84
89
|
"build": "tsup && tsc -p tsconfig.build.json --emitDeclarationOnly",
|
package/dist/chunk-6YY4Q3D4.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
// src/deployment.ts
|
|
2
|
-
var JUNIOR_HEARTBEAT_ROUTE = "/api/internal/heartbeat";
|
|
3
|
-
var JUNIOR_HEARTBEAT_CRON_SCHEDULE = "* * * * *";
|
|
4
|
-
var JUNIOR_CONVERSATION_WORK_CALLBACK_ROUTE = "/api/internal/agent/continue";
|
|
5
|
-
var LEGACY_JUNIOR_CONVERSATION_WORK_FUNCTION = "api/internal/agent/continue.ts";
|
|
6
|
-
|
|
7
|
-
export {
|
|
8
|
-
JUNIOR_HEARTBEAT_ROUTE,
|
|
9
|
-
JUNIOR_HEARTBEAT_CRON_SCHEDULE,
|
|
10
|
-
JUNIOR_CONVERSATION_WORK_CALLBACK_ROUTE,
|
|
11
|
-
LEGACY_JUNIOR_CONVERSATION_WORK_FUNCTION
|
|
12
|
-
};
|