@sentry/junior 0.106.0 → 0.107.1
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-KR5BCWOK.js → agent-hooks-ICPIJAFY.js} +9 -7
- package/dist/api/conversations/detail.d.ts +1 -1
- package/dist/api/conversations/events.d.ts +14 -0
- package/dist/api/conversations/schema.d.ts +196 -463
- package/dist/api/schema.d.ts +2 -7
- package/dist/api/schema.js +10 -8
- package/dist/api.js +377 -810
- package/dist/app.js +3586 -3614
- package/dist/{catalog-runtime-5CVM2DOF.js → catalog-runtime-FOFNPR3P.js} +3 -2
- package/dist/chat/agent/prompt.d.ts +1 -1
- package/dist/chat/agent/request.d.ts +28 -29
- package/dist/chat/agent/resume.d.ts +7 -7
- package/dist/chat/agent/session.d.ts +5 -6
- package/dist/chat/agent/tools.d.ts +3 -3
- package/dist/chat/agent-dispatch/runner.d.ts +2 -0
- package/dist/chat/config.d.ts +2 -2
- package/dist/chat/conversations/history.d.ts +582 -167
- package/dist/chat/conversations/message-projection.d.ts +6 -0
- package/dist/chat/conversations/message-summaries.d.ts +9 -0
- package/dist/chat/conversations/messages.d.ts +13 -27
- package/dist/chat/conversations/projection.d.ts +30 -53
- package/dist/chat/conversations/provenance.d.ts +42 -0
- package/dist/chat/conversations/search.d.ts +2 -2
- package/dist/chat/conversations/sql/conversation-row.d.ts +1 -1
- package/dist/chat/conversations/sql/event-lock.d.ts +3 -0
- package/dist/chat/conversations/sql/history.d.ts +3 -3
- package/dist/chat/conversations/sql/privacy.d.ts +27 -0
- package/dist/chat/conversations/sql/purge.d.ts +2 -10
- package/dist/chat/conversations/sql/store.d.ts +0 -5
- package/dist/chat/conversations/store.d.ts +8 -13
- package/dist/chat/conversations/turn-lifecycle.d.ts +41 -0
- package/dist/chat/db.d.ts +4 -10
- package/dist/chat/model-profile.d.ts +10 -0
- package/dist/chat/oauth-flow.d.ts +0 -5
- package/dist/chat/pi/conversation-events.d.ts +33 -0
- package/dist/chat/pi/sql-model-usage.d.ts +10 -0
- package/dist/chat/plugins/agent-hooks.d.ts +4 -2
- package/dist/chat/resource-events/ingest.d.ts +0 -13
- package/dist/chat/runtime/delivered-turn-state.d.ts +1 -1
- package/dist/chat/runtime/generated-artifacts.d.ts +1 -1
- package/dist/chat/runtime/reply-executor.d.ts +2 -0
- package/dist/chat/runtime/slack-resume.d.ts +23 -28
- package/dist/chat/runtime/slack-runtime.d.ts +2 -0
- package/dist/chat/runtime/turn.d.ts +14 -1
- package/dist/chat/services/context-compaction-marker.d.ts +0 -1
- package/dist/chat/services/context-compaction.d.ts +1 -0
- package/dist/chat/services/conversation-memory.d.ts +9 -0
- package/dist/chat/services/plugin-auth-orchestration.d.ts +1 -4
- package/dist/chat/services/subscribed-decision.d.ts +1 -1
- package/dist/chat/services/turn-failure-response.d.ts +10 -3
- package/dist/chat/services/turn-result.d.ts +7 -12
- package/dist/chat/services/{turn-reasoning-level.d.ts → turn-router.d.ts} +12 -8
- package/dist/chat/services/turn-session-record.d.ts +15 -16
- package/dist/chat/slack/adapter.d.ts +2 -2
- package/dist/chat/slack/errors.d.ts +2 -0
- package/dist/chat/slack/outbound.d.ts +0 -1
- package/dist/chat/slack/reply.d.ts +2 -8
- package/dist/chat/slack/tools/channel-capabilities.d.ts +2 -2
- package/dist/chat/slack/tools/{send-message.d.ts → send-files.d.ts} +27 -19
- package/dist/chat/state/conversation.d.ts +4 -4
- package/dist/chat/state/turn-id.d.ts +2 -0
- package/dist/chat/state/turn-session-keys.d.ts +6 -0
- package/dist/chat/state/turn-session.d.ts +11 -9
- package/dist/chat/task-execution/state.d.ts +6 -1
- package/dist/chat/task-execution/store.d.ts +1 -1
- package/dist/chat/tool-support/pi-tool-adapter.d.ts +1 -1
- package/dist/chat/tool-support/tool-execution-report.d.ts +1 -0
- package/dist/chat/tools/handoff/tool.d.ts +2 -2
- package/dist/chat/tools/sandbox/file-uploads.d.ts +28 -6
- package/dist/chat/tools/types.d.ts +6 -9
- package/dist/chat/tools/web/image-generate.d.ts +4 -6
- package/dist/{chunk-DDRQ4U7I.js → chunk-4YF7Z6IA.js} +390 -270
- package/dist/{chunk-AZ5OMSN5.js → chunk-AUUOHQAT.js} +2 -2
- package/dist/chunk-B2Z2H66D.js +250 -0
- package/dist/{chunk-4W4O4DCV.js → chunk-CQ7KSO2B.js} +75 -45
- package/dist/{chunk-MJSJAHBW.js → chunk-DY7TRYB5.js} +1 -1
- package/dist/{chunk-GPPUTY5M.js → chunk-EDLNHZH3.js} +861 -891
- package/dist/{chunk-R5BFYK2O.js → chunk-IGHMVDWI.js} +134 -18
- package/dist/chunk-MU6HHZEN.js +99 -0
- package/dist/{chunk-XTKJPSMF.js → chunk-NVOTGWYX.js} +458 -684
- package/dist/{chunk-AEWZ7F65.js → chunk-O24R4DCK.js} +2 -179
- package/dist/{chunk-CCFROYAV.js → chunk-PUAMO4PI.js} +115 -125
- package/dist/{chunk-ZMRLBBD5.js → chunk-RMVOAJRL.js} +30 -13
- package/dist/{chunk-3NYUCBLE.js → chunk-SPUAJVVH.js} +6 -4
- package/dist/{chunk-4UYIRWDW.js → chunk-SS67LUOK.js} +41 -290
- package/dist/{chunk-FXFQNHRU.js → chunk-VFUK3X5B.js} +4 -2
- package/dist/{chunk-3MPPVPGZ.js → chunk-VH6KWKG2.js} +2 -2
- package/dist/chunk-VIXFG2VC.js +182 -0
- package/dist/{chunk-BKM4UXUD.js → chunk-YFQ7CQDE.js} +669 -18
- package/dist/{chunk-77LHNQK4.js → chunk-YIPD3L6L.js} +4 -2
- package/dist/{chunk-3OUSJPR7.js → chunk-YNP2ATQX.js} +6 -4
- package/dist/{chunk-WR7H7VLJ.js → chunk-YT72TOEK.js} +2 -2
- package/dist/cli/chat.js +21 -20
- package/dist/cli/check.js +4 -3
- package/dist/cli/plugins.js +11 -9
- package/dist/cli/snapshot-warmup.js +7 -5
- package/dist/cli/upgrade.js +2041 -105
- package/dist/db/schema/{agent-steps.d.ts → conversation-events.d.ts} +37 -21
- package/dist/db/schema.d.ts +28 -159
- package/dist/{db-S33LFWG2.js → db-DIGO4TGW.js} +6 -8
- package/dist/{runner-HA5XAL6K.js → runner-ACR2HAIC.js} +209 -101
- package/dist/{skills-722AXRV5.js → skills-ITNHBARB.js} +4 -3
- package/dist/{validation-EUI2UFRM.js → validation-AGQ46ZGV.js} +4 -3
- package/migrations/0005_conversation_events.sql +122 -0
- package/migrations/README.md +23 -10
- package/migrations/meta/0005_snapshot.json +948 -0
- package/migrations/meta/_journal.json +7 -0
- package/package.json +5 -5
- package/dist/api/conversations/activity.d.ts +0 -40
- package/dist/api/conversations/detail-projection.d.ts +0 -11
- package/dist/api/conversations/detail.query.d.ts +0 -3
- package/dist/api/conversations/subagent.d.ts +0 -10
- package/dist/api/conversations/transcript.d.ts +0 -28
- package/dist/chat/conversations/legacy-advisor-session.d.ts +0 -7
- package/dist/chat/conversations/legacy-import.d.ts +0 -38
- package/dist/chat/conversations/sql/legacy-history-import.d.ts +0 -55
- package/dist/chat/conversations/sql/messages.d.ts +0 -4
- package/dist/chat/conversations/visible-compactions.d.ts +0 -11
- package/dist/chat/conversations/visible-messages.d.ts +0 -47
- package/dist/chat/services/reply-delivery-plan.d.ts +0 -5
- package/dist/chat/state/session-log.d.ts +0 -384
- package/dist/chunk-P4P7O5WG.js +0 -1072
- package/dist/chunk-XIMUQ4IU.js +0 -147
- package/dist/db/schema/conversation-messages.d.ts +0 -153
- package/dist/handlers/github-webhook/check-suite.d.ts +0 -3
- package/dist/handlers/github-webhook/issue-comment.d.ts +0 -3
- package/dist/handlers/github-webhook/pull-request-review-comment.d.ts +0 -3
- package/dist/handlers/github-webhook/pull-request-review.d.ts +0 -3
- package/dist/handlers/github-webhook/pull-request.d.ts +0 -3
- package/dist/handlers/github-webhook/resource.d.ts +0 -10
- package/dist/handlers/github-webhook.d.ts +0 -15
- package/dist/legacy-import-TMJISRKO.js +0 -18
|
@@ -1,64 +1,73 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ConversationTurnLifecycleService,
|
|
2
3
|
buildDeliveredTurnStatePatch,
|
|
3
|
-
|
|
4
|
+
finalizeFailedTurnReplyWithEvent,
|
|
4
5
|
processPluginTask,
|
|
5
6
|
scheduleSessionCompletedPluginTasks
|
|
6
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-CQ7KSO2B.js";
|
|
7
8
|
import "./chunk-KNFROR7R.js";
|
|
8
9
|
import {
|
|
10
|
+
buildConversationContext,
|
|
9
11
|
coerceThreadArtifactsState,
|
|
10
12
|
completeDeliveredTurn,
|
|
11
13
|
getPersistedSandboxState,
|
|
12
14
|
getPersistedThreadState,
|
|
13
|
-
markTurnFailed,
|
|
14
|
-
persistThreadStateById,
|
|
15
|
-
startActiveTurn
|
|
16
|
-
} from "./chunk-BKM4UXUD.js";
|
|
17
|
-
import {
|
|
18
|
-
coerceThreadConversationState
|
|
19
|
-
} from "./chunk-XIMUQ4IU.js";
|
|
20
|
-
import {
|
|
21
|
-
commitMessages,
|
|
22
|
-
loadProjection
|
|
23
|
-
} from "./chunk-DDRQ4U7I.js";
|
|
24
|
-
import {
|
|
25
|
-
buildConversationContext,
|
|
26
15
|
hydrateConversationMessages,
|
|
27
16
|
markConversationMessage,
|
|
17
|
+
markTurnFailed,
|
|
28
18
|
normalizeConversationText,
|
|
19
|
+
persistConversationMessages,
|
|
20
|
+
persistThreadStateById,
|
|
21
|
+
persistWithRetry,
|
|
22
|
+
recordDeliveredAssistantMessage,
|
|
23
|
+
startActiveTurn,
|
|
29
24
|
updateConversationStats,
|
|
30
25
|
upsertConversationMessage
|
|
31
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-YFQ7CQDE.js";
|
|
27
|
+
import {
|
|
28
|
+
coerceThreadConversationState,
|
|
29
|
+
loadProjection
|
|
30
|
+
} from "./chunk-4YF7Z6IA.js";
|
|
31
|
+
import "./chunk-MU6HHZEN.js";
|
|
32
32
|
import "./chunk-PDO5BLNM.js";
|
|
33
|
-
import "./chunk-
|
|
34
|
-
import "./chunk-
|
|
33
|
+
import "./chunk-RMVOAJRL.js";
|
|
34
|
+
import "./chunk-AUUOHQAT.js";
|
|
35
35
|
import "./chunk-G3E7SCME.js";
|
|
36
|
-
import "./chunk-
|
|
37
|
-
import "./chunk-
|
|
36
|
+
import "./chunk-B2Z2H66D.js";
|
|
37
|
+
import "./chunk-VH6KWKG2.js";
|
|
38
38
|
import {
|
|
39
|
-
|
|
40
|
-
} from "./chunk-
|
|
39
|
+
getConversationEventStore
|
|
40
|
+
} from "./chunk-NVOTGWYX.js";
|
|
41
|
+
import "./chunk-4ZNGQH7C.js";
|
|
41
42
|
import {
|
|
42
43
|
stripRuntimeTurnContext,
|
|
43
44
|
trimTrailingAssistantMessages
|
|
44
|
-
} from "./chunk-
|
|
45
|
-
import "./chunk-
|
|
45
|
+
} from "./chunk-SS67LUOK.js";
|
|
46
|
+
import "./chunk-VFUK3X5B.js";
|
|
46
47
|
import "./chunk-RT5BUHR5.js";
|
|
47
48
|
import "./chunk-B7PUBQQM.js";
|
|
49
|
+
import "./chunk-VIXFG2VC.js";
|
|
48
50
|
import {
|
|
49
51
|
logException
|
|
50
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-O24R4DCK.js";
|
|
51
53
|
import "./chunk-OB42YVAE.js";
|
|
52
54
|
import "./chunk-6GWA276C.js";
|
|
53
55
|
import "./chunk-7FBGKXPE.js";
|
|
54
56
|
import "./chunk-MLKGABMK.js";
|
|
55
57
|
|
|
56
58
|
// src/chat/local/runner.ts
|
|
59
|
+
import { randomUUID } from "crypto";
|
|
57
60
|
import {
|
|
58
61
|
createLocalSource,
|
|
59
62
|
localDestinationSchema
|
|
60
63
|
} from "@sentry/junior-plugin-api";
|
|
61
|
-
var
|
|
64
|
+
var SENTRY_EVENT_ID_PATTERN = /^[a-f0-9]{32}$/i;
|
|
65
|
+
var LOCAL_FAILURE_EVENT_NAMES = {
|
|
66
|
+
agent_run_failed: "local_agent_run_failed",
|
|
67
|
+
delivery_failed: "local_reply_delivery_failed",
|
|
68
|
+
model_execution_failed: "local_model_execution_failed",
|
|
69
|
+
persistence_failed: "local_turn_persistence_failed"
|
|
70
|
+
};
|
|
62
71
|
function localDestination(conversationId) {
|
|
63
72
|
const parsed = localDestinationSchema.safeParse({
|
|
64
73
|
platform: "local",
|
|
@@ -69,16 +78,18 @@ function localDestination(conversationId) {
|
|
|
69
78
|
}
|
|
70
79
|
return parsed.data;
|
|
71
80
|
}
|
|
72
|
-
function localTurnId(
|
|
73
|
-
return `local-turn-${
|
|
74
|
-
}
|
|
75
|
-
function localReply(reply) {
|
|
76
|
-
return {
|
|
77
|
-
text: reply.text
|
|
78
|
-
};
|
|
81
|
+
function localTurnId() {
|
|
82
|
+
return `local-turn-${randomUUID()}`;
|
|
79
83
|
}
|
|
80
|
-
function
|
|
81
|
-
|
|
84
|
+
function captureLocalBoundaryFailure(args) {
|
|
85
|
+
const eventId = args.capture(
|
|
86
|
+
args.error,
|
|
87
|
+
LOCAL_FAILURE_EVENT_NAMES[args.failureCode],
|
|
88
|
+
{ conversationId: args.conversationId, runId: args.turnId },
|
|
89
|
+
{ "app.ai.failure_code": args.failureCode },
|
|
90
|
+
"Local agent turn failed at its owning runtime boundary"
|
|
91
|
+
);
|
|
92
|
+
return eventId && SENTRY_EVENT_ID_PATTERN.test(eventId) ? eventId : void 0;
|
|
82
93
|
}
|
|
83
94
|
async function loadLocalPiMessages(args) {
|
|
84
95
|
const projection = await loadProjection({
|
|
@@ -89,21 +100,6 @@ async function loadLocalPiMessages(args) {
|
|
|
89
100
|
}
|
|
90
101
|
return stripRuntimeTurnContext(trimTrailingAssistantMessages(projection));
|
|
91
102
|
}
|
|
92
|
-
async function persistDeliveredLocalTurnState(conversationId, patch) {
|
|
93
|
-
let lastError;
|
|
94
|
-
for (let attempt = 1; attempt <= DELIVERED_STATE_PERSIST_ATTEMPTS; attempt += 1) {
|
|
95
|
-
try {
|
|
96
|
-
await persistThreadStateById(conversationId, patch);
|
|
97
|
-
return;
|
|
98
|
-
} catch (error) {
|
|
99
|
-
lastError = error;
|
|
100
|
-
if (attempt < DELIVERED_STATE_PERSIST_ATTEMPTS) {
|
|
101
|
-
await sleep(attempt * 100);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
throw lastError;
|
|
106
|
-
}
|
|
107
103
|
async function runLocalAgentTurn(input, deps) {
|
|
108
104
|
const text = input.message.trim();
|
|
109
105
|
if (!text) {
|
|
@@ -114,6 +110,7 @@ async function runLocalAgentTurn(input, deps) {
|
|
|
114
110
|
}
|
|
115
111
|
const destination = localDestination(input.conversationId);
|
|
116
112
|
const source = createLocalSource(destination.conversationId);
|
|
113
|
+
const lifecycle = deps.turnLifecycle ?? new ConversationTurnLifecycleService(getConversationEventStore());
|
|
117
114
|
const now = deps.now ?? (() => Date.now());
|
|
118
115
|
const persisted = await getPersistedThreadState(input.conversationId);
|
|
119
116
|
const conversation = coerceThreadConversationState(persisted);
|
|
@@ -126,8 +123,7 @@ async function runLocalAgentTurn(input, deps) {
|
|
|
126
123
|
const initialArtifacts = artifacts;
|
|
127
124
|
const initialSandboxId = sandboxId;
|
|
128
125
|
const initialSandboxDependencyProfileHash = sandboxDependencyProfileHash;
|
|
129
|
-
const
|
|
130
|
-
const turnId = localTurnId(sequence);
|
|
126
|
+
const turnId = localTurnId();
|
|
131
127
|
const userMessageId = `${turnId}:user`;
|
|
132
128
|
const startedAtMs = now();
|
|
133
129
|
upsertConversationMessage(conversation, {
|
|
@@ -145,27 +141,75 @@ async function runLocalAgentTurn(input, deps) {
|
|
|
145
141
|
replied: false
|
|
146
142
|
}
|
|
147
143
|
});
|
|
144
|
+
await persistConversationMessages({
|
|
145
|
+
conversation,
|
|
146
|
+
conversationId: input.conversationId
|
|
147
|
+
});
|
|
148
|
+
await lifecycle.start({
|
|
149
|
+
conversationId: input.conversationId,
|
|
150
|
+
createdAtMs: now(),
|
|
151
|
+
inputMessageIds: [userMessageId],
|
|
152
|
+
surface: "internal",
|
|
153
|
+
turnId
|
|
154
|
+
});
|
|
148
155
|
startActiveTurn({
|
|
149
156
|
conversation,
|
|
150
157
|
nextTurnId: turnId,
|
|
151
158
|
updateConversationStats
|
|
152
159
|
});
|
|
153
|
-
await persistThreadStateById(input.conversationId, { conversation });
|
|
154
160
|
let reply;
|
|
155
161
|
let completedState;
|
|
156
|
-
let
|
|
162
|
+
let failureCode = "persistence_failed";
|
|
163
|
+
let modelFailureEventId;
|
|
164
|
+
let modelFailureCaptureAttempted = false;
|
|
157
165
|
const localActor = {
|
|
158
166
|
fullName: "Local CLI",
|
|
159
167
|
platform: "local",
|
|
160
168
|
userId: "local-cli",
|
|
161
169
|
userName: "local"
|
|
162
170
|
};
|
|
171
|
+
let assistantMessageDelivered = false;
|
|
172
|
+
const deliverAssistantMessage = async (message) => {
|
|
173
|
+
if (!message.text.trim()) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
failureCode = "delivery_failed";
|
|
177
|
+
await deps.deliverReply({ text: message.text });
|
|
178
|
+
assistantMessageDelivered = true;
|
|
179
|
+
recordDeliveredAssistantMessage({
|
|
180
|
+
conversation,
|
|
181
|
+
sessionId: turnId,
|
|
182
|
+
text: message.text,
|
|
183
|
+
userMessageId
|
|
184
|
+
});
|
|
185
|
+
try {
|
|
186
|
+
await persistWithRetry(
|
|
187
|
+
() => persistConversationMessages({
|
|
188
|
+
conversation,
|
|
189
|
+
conversationId: input.conversationId
|
|
190
|
+
})
|
|
191
|
+
);
|
|
192
|
+
} catch (error) {
|
|
193
|
+
logException(
|
|
194
|
+
new Error("Accepted assistant message persistence failed"),
|
|
195
|
+
"local_assistant_message_post_delivery_persist_failed",
|
|
196
|
+
{ conversationId: input.conversationId },
|
|
197
|
+
{ "error.type": error instanceof Error ? error.name : typeof error },
|
|
198
|
+
"Failed to persist an accepted local assistant message"
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
failureCode = "agent_run_failed";
|
|
202
|
+
};
|
|
163
203
|
try {
|
|
164
|
-
|
|
204
|
+
await persistThreadStateById(input.conversationId, { conversation });
|
|
205
|
+
const piMessages = await (deps.loadPiMessages ?? loadLocalPiMessages)({
|
|
165
206
|
conversationId: input.conversationId
|
|
166
207
|
});
|
|
167
|
-
|
|
208
|
+
failureCode = "agent_run_failed";
|
|
168
209
|
const outcome = await deps.agentRunner.run({
|
|
210
|
+
conversationId: input.conversationId,
|
|
211
|
+
turnId,
|
|
212
|
+
runId: turnId,
|
|
169
213
|
input: {
|
|
170
214
|
messageText: text,
|
|
171
215
|
conversationContext: buildConversationContext(conversation, {
|
|
@@ -180,12 +224,7 @@ async function runLocalAgentTurn(input, deps) {
|
|
|
180
224
|
destination,
|
|
181
225
|
source,
|
|
182
226
|
actor: localActor,
|
|
183
|
-
surface: "internal"
|
|
184
|
-
correlation: {
|
|
185
|
-
conversationId: input.conversationId,
|
|
186
|
-
turnId,
|
|
187
|
-
runId: turnId
|
|
188
|
-
}
|
|
227
|
+
surface: "internal"
|
|
189
228
|
},
|
|
190
229
|
policy: {
|
|
191
230
|
authorizationFlowMode: "disabled"
|
|
@@ -201,7 +240,6 @@ async function runLocalAgentTurn(input, deps) {
|
|
|
201
240
|
onStatus: async (status) => {
|
|
202
241
|
await deps.onStatus?.(status.text);
|
|
203
242
|
},
|
|
204
|
-
onTextDelta: deps.onTextDelta,
|
|
205
243
|
onToolInvocation: async (invocation) => {
|
|
206
244
|
await deps.onToolInvocation?.(invocation);
|
|
207
245
|
},
|
|
@@ -209,6 +247,9 @@ async function runLocalAgentTurn(input, deps) {
|
|
|
209
247
|
await deps.onToolResult?.(result);
|
|
210
248
|
}
|
|
211
249
|
},
|
|
250
|
+
delivery: {
|
|
251
|
+
onAssistantMessage: deliverAssistantMessage
|
|
252
|
+
},
|
|
212
253
|
durability: {
|
|
213
254
|
onArtifactStateUpdated: async (nextArtifacts) => {
|
|
214
255
|
artifacts = nextArtifacts;
|
|
@@ -235,11 +276,17 @@ async function runLocalAgentTurn(input, deps) {
|
|
|
235
276
|
throw new Error(`Local agent run ended with ${outcome.status}`);
|
|
236
277
|
}
|
|
237
278
|
reply = outcome.result;
|
|
238
|
-
|
|
279
|
+
modelFailureCaptureAttempted = reply.diagnostics.outcome !== "success";
|
|
280
|
+
const finalized = finalizeFailedTurnReplyWithEvent({
|
|
239
281
|
reply,
|
|
240
|
-
logException,
|
|
282
|
+
logException: deps.logException ?? logException,
|
|
241
283
|
context: { conversationId: input.conversationId }
|
|
242
284
|
});
|
|
285
|
+
reply = finalized.reply;
|
|
286
|
+
modelFailureEventId = finalized.eventId;
|
|
287
|
+
if (reply.diagnostics.outcome !== "success") {
|
|
288
|
+
await deliverAssistantMessage({ text: reply.text });
|
|
289
|
+
}
|
|
243
290
|
completedState = buildDeliveredTurnStatePatch({
|
|
244
291
|
artifacts,
|
|
245
292
|
conversation,
|
|
@@ -247,52 +294,113 @@ async function runLocalAgentTurn(input, deps) {
|
|
|
247
294
|
sessionId: turnId,
|
|
248
295
|
userMessageId
|
|
249
296
|
});
|
|
250
|
-
await deps.deliverReply(localReply(reply));
|
|
251
297
|
} catch (error) {
|
|
252
|
-
|
|
253
|
-
|
|
298
|
+
const failureEventId = modelFailureCaptureAttempted && failureCode === "agent_run_failed" ? modelFailureEventId : captureLocalBoundaryFailure({
|
|
299
|
+
capture: deps.logException ?? logException,
|
|
300
|
+
conversationId: input.conversationId,
|
|
301
|
+
error,
|
|
302
|
+
failureCode,
|
|
303
|
+
turnId
|
|
304
|
+
});
|
|
305
|
+
try {
|
|
306
|
+
markTurnFailed({
|
|
307
|
+
conversation,
|
|
308
|
+
nowMs: now(),
|
|
309
|
+
sessionId: turnId,
|
|
310
|
+
userMessageId,
|
|
311
|
+
markConversationMessage,
|
|
312
|
+
updateConversationStats
|
|
313
|
+
});
|
|
314
|
+
await persistThreadStateById(input.conversationId, {
|
|
315
|
+
artifacts: initialArtifacts,
|
|
316
|
+
conversation,
|
|
317
|
+
sandboxId: initialSandboxId ?? "",
|
|
318
|
+
sandboxDependencyProfileHash: initialSandboxDependencyProfileHash ?? ""
|
|
319
|
+
});
|
|
320
|
+
} catch (persistenceError) {
|
|
321
|
+
const persistenceEventId = captureLocalBoundaryFailure({
|
|
322
|
+
capture: deps.logException ?? logException,
|
|
254
323
|
conversationId: input.conversationId,
|
|
255
|
-
|
|
256
|
-
|
|
324
|
+
error: persistenceError,
|
|
325
|
+
failureCode: "persistence_failed",
|
|
326
|
+
turnId
|
|
257
327
|
});
|
|
328
|
+
await lifecycle.fail({
|
|
329
|
+
conversationId: input.conversationId,
|
|
330
|
+
createdAtMs: now(),
|
|
331
|
+
...persistenceEventId ? { eventId: persistenceEventId } : {},
|
|
332
|
+
failureCode: "persistence_failed",
|
|
333
|
+
turnId
|
|
334
|
+
});
|
|
335
|
+
throw new AggregateError(
|
|
336
|
+
[error, persistenceError],
|
|
337
|
+
"Local turn failure state could not be persisted"
|
|
338
|
+
);
|
|
258
339
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
updateConversationStats
|
|
340
|
+
await lifecycle.fail({
|
|
341
|
+
conversationId: input.conversationId,
|
|
342
|
+
createdAtMs: now(),
|
|
343
|
+
...failureEventId ? { eventId: failureEventId } : {},
|
|
344
|
+
failureCode,
|
|
345
|
+
turnId
|
|
266
346
|
});
|
|
347
|
+
throw error;
|
|
348
|
+
}
|
|
349
|
+
try {
|
|
267
350
|
await persistThreadStateById(input.conversationId, {
|
|
268
|
-
artifacts:
|
|
269
|
-
conversation,
|
|
270
|
-
sandboxId:
|
|
271
|
-
sandboxDependencyProfileHash:
|
|
351
|
+
artifacts: completedState.artifacts ?? artifacts,
|
|
352
|
+
conversation: completedState.conversation,
|
|
353
|
+
sandboxId: reply.sandboxId ?? sandboxId,
|
|
354
|
+
sandboxDependencyProfileHash: reply.sandboxDependencyProfileHash ?? sandboxDependencyProfileHash
|
|
355
|
+
});
|
|
356
|
+
if (reply.piMessages?.length) {
|
|
357
|
+
await (deps.completeDeliveredTurn ?? completeDeliveredTurn)({
|
|
358
|
+
conversationId: input.conversationId,
|
|
359
|
+
sessionId: turnId,
|
|
360
|
+
sliceId: 1,
|
|
361
|
+
messages: reply.piMessages,
|
|
362
|
+
modelId: reply.diagnostics.modelId,
|
|
363
|
+
durationMs: reply.diagnostics.durationMs,
|
|
364
|
+
usage: reply.diagnostics.usage,
|
|
365
|
+
reasoningLevel: reply.diagnostics.reasoningLevel,
|
|
366
|
+
destination,
|
|
367
|
+
source,
|
|
368
|
+
actor: localActor,
|
|
369
|
+
surface: "internal",
|
|
370
|
+
logContext: {}
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
} catch (error) {
|
|
374
|
+
const persistenceEventId = captureLocalBoundaryFailure({
|
|
375
|
+
capture: deps.logException ?? logException,
|
|
376
|
+
conversationId: input.conversationId,
|
|
377
|
+
error,
|
|
378
|
+
failureCode: "persistence_failed",
|
|
379
|
+
turnId
|
|
380
|
+
});
|
|
381
|
+
await lifecycle.fail({
|
|
382
|
+
conversationId: input.conversationId,
|
|
383
|
+
createdAtMs: now(),
|
|
384
|
+
...persistenceEventId ? { eventId: persistenceEventId } : {},
|
|
385
|
+
failureCode: "persistence_failed",
|
|
386
|
+
turnId
|
|
272
387
|
});
|
|
273
388
|
throw error;
|
|
274
389
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
conversation: completedState.conversation,
|
|
278
|
-
sandboxId: reply.sandboxId ?? sandboxId,
|
|
279
|
-
sandboxDependencyProfileHash: reply.sandboxDependencyProfileHash ?? sandboxDependencyProfileHash
|
|
280
|
-
});
|
|
281
|
-
if (reply.piMessages?.length) {
|
|
282
|
-
await completeDeliveredTurn({
|
|
390
|
+
if (reply.diagnostics.outcome === "success") {
|
|
391
|
+
await lifecycle.complete({
|
|
283
392
|
conversationId: input.conversationId,
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
logContext: {}
|
|
393
|
+
createdAtMs: now(),
|
|
394
|
+
outcome: assistantMessageDelivered ? "success" : "no_reply",
|
|
395
|
+
turnId
|
|
396
|
+
});
|
|
397
|
+
} else {
|
|
398
|
+
await lifecycle.fail({
|
|
399
|
+
conversationId: input.conversationId,
|
|
400
|
+
createdAtMs: now(),
|
|
401
|
+
...modelFailureEventId ? { eventId: modelFailureEventId } : {},
|
|
402
|
+
failureCode: "model_execution_failed",
|
|
403
|
+
turnId
|
|
296
404
|
});
|
|
297
405
|
}
|
|
298
406
|
if (reply.diagnostics.outcome === "success") {
|
|
@@ -6,9 +6,10 @@ import {
|
|
|
6
6
|
parseSkillInvocation,
|
|
7
7
|
resetSkillDiscoveryCache,
|
|
8
8
|
stripFrontmatter
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-YT72TOEK.js";
|
|
10
|
+
import "./chunk-YIPD3L6L.js";
|
|
11
|
+
import "./chunk-VIXFG2VC.js";
|
|
12
|
+
import "./chunk-O24R4DCK.js";
|
|
12
13
|
import "./chunk-OB42YVAE.js";
|
|
13
14
|
import "./chunk-6GWA276C.js";
|
|
14
15
|
import "./chunk-B3IT5END.js";
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
validatePluginEgressCredentialHooks,
|
|
3
3
|
validatePluginRegistrations
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-DY7TRYB5.js";
|
|
5
|
+
import "./chunk-YIPD3L6L.js";
|
|
6
|
+
import "./chunk-VIXFG2VC.js";
|
|
7
|
+
import "./chunk-O24R4DCK.js";
|
|
7
8
|
import "./chunk-OB42YVAE.js";
|
|
8
9
|
import "./chunk-6GWA276C.js";
|
|
9
10
|
import "./chunk-B3IT5END.js";
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
ALTER TABLE "junior_agent_steps" RENAME TO "junior_conversation_events";--> statement-breakpoint
|
|
2
|
+
DO $$
|
|
3
|
+
BEGIN
|
|
4
|
+
IF EXISTS (
|
|
5
|
+
SELECT 1
|
|
6
|
+
FROM pg_constraint
|
|
7
|
+
WHERE conrelid = 'junior_conversation_events'::regclass
|
|
8
|
+
AND conname = 'junior_agent_steps_conversation_id_seq_pk'
|
|
9
|
+
) THEN
|
|
10
|
+
ALTER TABLE "junior_conversation_events"
|
|
11
|
+
RENAME CONSTRAINT "junior_agent_steps_conversation_id_seq_pk"
|
|
12
|
+
TO "junior_conversation_events_conversation_id_seq_pk";
|
|
13
|
+
ELSIF EXISTS (
|
|
14
|
+
SELECT 1
|
|
15
|
+
FROM pg_constraint
|
|
16
|
+
WHERE conrelid = 'junior_conversation_events'::regclass
|
|
17
|
+
AND conname = 'junior_agent_steps_pkey'
|
|
18
|
+
) THEN
|
|
19
|
+
ALTER TABLE "junior_conversation_events"
|
|
20
|
+
RENAME CONSTRAINT "junior_agent_steps_pkey"
|
|
21
|
+
TO "junior_conversation_events_conversation_id_seq_pk";
|
|
22
|
+
ELSE
|
|
23
|
+
RAISE EXCEPTION 'junior_agent_steps primary key constraint is missing';
|
|
24
|
+
END IF;
|
|
25
|
+
END
|
|
26
|
+
$$;--> statement-breakpoint
|
|
27
|
+
DO $$
|
|
28
|
+
BEGIN
|
|
29
|
+
IF EXISTS (
|
|
30
|
+
SELECT 1
|
|
31
|
+
FROM pg_constraint
|
|
32
|
+
WHERE conrelid = 'junior_conversation_events'::regclass
|
|
33
|
+
AND conname = 'junior_agent_steps_conversation_id_junior_conversations_conversation_id_fk'
|
|
34
|
+
) THEN
|
|
35
|
+
ALTER TABLE "junior_conversation_events"
|
|
36
|
+
RENAME CONSTRAINT "junior_agent_steps_conversation_id_junior_conversations_conversation_id_fk"
|
|
37
|
+
TO "junior_conversation_events_conversation_id_junior_conversations_conversation_id_fk";
|
|
38
|
+
ELSIF EXISTS (
|
|
39
|
+
SELECT 1
|
|
40
|
+
FROM pg_constraint
|
|
41
|
+
WHERE conrelid = 'junior_conversation_events'::regclass
|
|
42
|
+
AND conname = 'junior_agent_steps_conversation_id_fkey'
|
|
43
|
+
) THEN
|
|
44
|
+
ALTER TABLE "junior_conversation_events"
|
|
45
|
+
RENAME CONSTRAINT "junior_agent_steps_conversation_id_fkey"
|
|
46
|
+
TO "junior_conversation_events_conversation_id_junior_conversations_conversation_id_fk";
|
|
47
|
+
ELSE
|
|
48
|
+
RAISE EXCEPTION 'junior_agent_steps conversation foreign key constraint is missing';
|
|
49
|
+
END IF;
|
|
50
|
+
END
|
|
51
|
+
$$;--> statement-breakpoint
|
|
52
|
+
ALTER INDEX "junior_agent_steps_epoch_idx" RENAME TO "junior_conversation_events_history_version_idx";--> statement-breakpoint
|
|
53
|
+
ALTER TABLE "junior_conversation_events" RENAME COLUMN "context_epoch" TO "history_version";--> statement-breakpoint
|
|
54
|
+
ALTER TABLE "junior_conversation_events" ADD COLUMN "schema_version" integer DEFAULT 1 NOT NULL;--> statement-breakpoint
|
|
55
|
+
ALTER TABLE "junior_conversation_events" DROP COLUMN "role";--> statement-breakpoint
|
|
56
|
+
ALTER TABLE "junior_conversation_events" ADD COLUMN "idempotency_key" text;--> statement-breakpoint
|
|
57
|
+
CREATE UNIQUE INDEX "junior_conversation_events_idempotency_idx" ON "junior_conversation_events" USING btree ("conversation_id","idempotency_key");--> statement-breakpoint
|
|
58
|
+
CREATE INDEX "junior_conversation_events_type_idx" ON "junior_conversation_events" USING btree ("conversation_id","type","seq");--> statement-breakpoint
|
|
59
|
+
CREATE INDEX "junior_conversation_events_message_search_idx" ON "junior_conversation_events" USING gin (to_tsvector('english', "payload"->>'text')) WHERE "type" = 'message';--> statement-breakpoint
|
|
60
|
+
UPDATE "junior_conversation_events"
|
|
61
|
+
SET
|
|
62
|
+
"schema_version" = 1,
|
|
63
|
+
"type" = 'agent_step',
|
|
64
|
+
"payload" = CASE
|
|
65
|
+
WHEN jsonb_typeof("payload") = 'object'
|
|
66
|
+
THEN "payload" - 'schemaVersion'
|
|
67
|
+
ELSE "payload"
|
|
68
|
+
END
|
|
69
|
+
WHERE "type" = 'pi_message';--> statement-breakpoint
|
|
70
|
+
UPDATE "junior_conversation_events"
|
|
71
|
+
SET "payload" = "payload" - 'historyMode'
|
|
72
|
+
WHERE "type" = 'subagent_started'
|
|
73
|
+
AND jsonb_typeof("payload") = 'object'
|
|
74
|
+
AND "payload" ? 'historyMode';--> statement-breakpoint
|
|
75
|
+
UPDATE "junior_conversation_events"
|
|
76
|
+
SET "payload" = "payload" - 'args'
|
|
77
|
+
WHERE "type" = 'tool_execution_started'
|
|
78
|
+
AND jsonb_typeof("payload") = 'object'
|
|
79
|
+
AND "payload" ? 'args';--> statement-breakpoint
|
|
80
|
+
UPDATE "junior_conversation_events"
|
|
81
|
+
SET "type" = 'messages_summarized'
|
|
82
|
+
WHERE "type" = 'visible_context_compacted';--> statement-breakpoint
|
|
83
|
+
UPDATE "junior_conversation_events" AS snapshot
|
|
84
|
+
SET "payload" =
|
|
85
|
+
(snapshot."payload" - 'compactions') ||
|
|
86
|
+
jsonb_build_object(
|
|
87
|
+
'historyFromSeq',
|
|
88
|
+
coalesce((
|
|
89
|
+
SELECT max(recorded."seq") + 1
|
|
90
|
+
FROM "junior_conversation_events" AS recorded
|
|
91
|
+
WHERE recorded."conversation_id" = snapshot."conversation_id"
|
|
92
|
+
AND recorded."seq" < snapshot."seq"
|
|
93
|
+
AND recorded."type" = 'message'
|
|
94
|
+
AND EXISTS (
|
|
95
|
+
SELECT 1
|
|
96
|
+
FROM jsonb_array_elements(snapshot."payload"->'compactions') AS compaction,
|
|
97
|
+
jsonb_array_elements_text(compaction->'coveredMessageIds') AS covered_id(value)
|
|
98
|
+
WHERE covered_id.value = recorded."payload"->>'messageId'
|
|
99
|
+
)
|
|
100
|
+
), 0),
|
|
101
|
+
'compactions',
|
|
102
|
+
coalesce((
|
|
103
|
+
SELECT jsonb_agg(
|
|
104
|
+
(CASE
|
|
105
|
+
WHEN EXISTS (
|
|
106
|
+
SELECT 1
|
|
107
|
+
FROM "junior_conversation_events" AS recorded
|
|
108
|
+
WHERE recorded."conversation_id" = snapshot."conversation_id"
|
|
109
|
+
AND recorded."type" = 'message'
|
|
110
|
+
)
|
|
111
|
+
THEN compaction - 'coveredMessageIds'
|
|
112
|
+
ELSE compaction
|
|
113
|
+
END) ||
|
|
114
|
+
jsonb_build_object(
|
|
115
|
+
'coveredMessageCount',
|
|
116
|
+
jsonb_array_length(compaction->'coveredMessageIds')
|
|
117
|
+
)
|
|
118
|
+
)
|
|
119
|
+
FROM jsonb_array_elements(snapshot."payload"->'compactions') AS compaction
|
|
120
|
+
), '[]'::jsonb)
|
|
121
|
+
)
|
|
122
|
+
WHERE snapshot."type" = 'messages_summarized';--> statement-breakpoint
|
package/migrations/README.md
CHANGED
|
@@ -1,14 +1,27 @@
|
|
|
1
|
-
# SQL migrations
|
|
1
|
+
# SQL migrations
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Drizzle ORM's migrator before any data backfills run.
|
|
3
|
+
`src/db/schema.ts` is the Drizzle schema entrypoint. This directory is the
|
|
4
|
+
append-only history used to bring an existing database to that schema.
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
`junior upgrade` runs the ordered migration list in `src/cli/upgrade.ts`. Core
|
|
7
|
+
SQL runs under a migration lock and is recorded in
|
|
8
|
+
`drizzle.__drizzle_junior_core`, so reruns do not reapply it. Register backfills
|
|
9
|
+
after the schema migration they require.
|
|
10
|
+
|
|
11
|
+
## Add a migration
|
|
12
|
+
|
|
13
|
+
1. Change the owning table definition under `src/db/schema/`.
|
|
8
14
|
2. Run `pnpm --filter @sentry/junior db:generate --name <migration_name>`.
|
|
9
|
-
3.
|
|
15
|
+
3. Review the generated SQL and commit it with `meta/_journal.json` and its
|
|
16
|
+
snapshot.
|
|
17
|
+
|
|
18
|
+
- Prefer SQL for schema changes and deterministic transformations of rows in
|
|
19
|
+
the same database.
|
|
20
|
+
- Use an application data migration only for external data or work that must be
|
|
21
|
+
decoded in application code; keep it bounded and rerunnable.
|
|
22
|
+
- Never edit, rename, reorder, or delete an applied SQL migration or its
|
|
23
|
+
metadata. Add a new migration to correct it.
|
|
10
24
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
migrations are applied by Drizzle in journal order.
|
|
25
|
+
Migration loading, locking, and legacy baseline adoption live in
|
|
26
|
+
`src/chat/conversations/sql/migrations.ts`. Their integration coverage lives in
|
|
27
|
+
`tests/integration/conversation-sql.test.ts`.
|