@sentry/junior 0.106.0 → 0.107.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agent-hooks-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 +2046 -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,78 +1,119 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
} from "./chunk-
|
|
2
|
+
agentTurnUsageSchema
|
|
3
|
+
} from "./chunk-MU6HHZEN.js";
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
} from "./chunk-
|
|
5
|
+
getStateAdapter
|
|
6
|
+
} from "./chunk-B2Z2H66D.js";
|
|
7
7
|
import {
|
|
8
8
|
contextProvenance,
|
|
9
|
-
|
|
9
|
+
createSqlConversationEventStore,
|
|
10
|
+
getConversationEventStore,
|
|
10
11
|
getConversationStore,
|
|
12
|
+
getSqlExecutor,
|
|
11
13
|
instructionActors,
|
|
12
|
-
instructionProvenanceFor
|
|
13
|
-
|
|
14
|
+
instructionProvenanceFor,
|
|
15
|
+
sanitizePostgresJson,
|
|
16
|
+
withConversationEventLock
|
|
17
|
+
} from "./chunk-NVOTGWYX.js";
|
|
14
18
|
import {
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
retainRuntimeTurnContext,
|
|
20
|
+
stripRuntimeTurnContext
|
|
21
|
+
} from "./chunk-SS67LUOK.js";
|
|
17
22
|
import {
|
|
18
|
-
logWarn,
|
|
19
23
|
toStoredSlackActor
|
|
20
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-VIXFG2VC.js";
|
|
25
|
+
import {
|
|
26
|
+
logWarn
|
|
27
|
+
} from "./chunk-O24R4DCK.js";
|
|
28
|
+
import {
|
|
29
|
+
isRecord,
|
|
30
|
+
toOptionalNumber,
|
|
31
|
+
toOptionalString
|
|
32
|
+
} from "./chunk-OB42YVAE.js";
|
|
21
33
|
|
|
22
34
|
// src/chat/conversations/projection.ts
|
|
23
35
|
import { isDeepStrictEqual } from "util";
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
36
|
+
|
|
37
|
+
// src/chat/pi/messages.ts
|
|
38
|
+
import { z } from "zod";
|
|
39
|
+
var piMessageSchema = z.object({
|
|
40
|
+
role: z.string()
|
|
41
|
+
}).passthrough().transform((value) => value);
|
|
42
|
+
var piContentMessageSchema = z.object({
|
|
43
|
+
content: z.array(z.unknown()),
|
|
44
|
+
role: z.string().min(1)
|
|
45
|
+
}).passthrough().transform((value) => value);
|
|
46
|
+
|
|
47
|
+
// src/chat/pi/conversation-events.ts
|
|
48
|
+
function authorizationObservationMessage(data, createdAtMs) {
|
|
49
|
+
const label = data.kind === "mcp" ? "MCP authorization" : "Authorization";
|
|
50
|
+
return piMessageSchema.parse({
|
|
27
51
|
role: "user",
|
|
28
52
|
content: [
|
|
29
53
|
{
|
|
30
54
|
type: "text",
|
|
31
|
-
text: `${label} completed for provider "${
|
|
55
|
+
text: `${label} completed for provider "${data.provider}". Continue the blocked request and retry the provider operation if needed.`
|
|
32
56
|
}
|
|
33
57
|
],
|
|
34
58
|
timestamp: createdAtMs
|
|
35
|
-
};
|
|
59
|
+
});
|
|
36
60
|
}
|
|
37
|
-
function
|
|
38
|
-
return
|
|
61
|
+
function messageEventProvenance(data) {
|
|
62
|
+
return data.provenance ?? contextProvenance;
|
|
39
63
|
}
|
|
40
|
-
function
|
|
64
|
+
function durableMessages(message) {
|
|
65
|
+
return stripRuntimeTurnContext([piMessageSchema.parse(message)]);
|
|
66
|
+
}
|
|
67
|
+
function projectConversationEvents(events, options) {
|
|
41
68
|
const messages = [];
|
|
42
69
|
const provenance = [];
|
|
43
70
|
const seqs = [];
|
|
44
71
|
let modelProfile = "standard";
|
|
45
72
|
let modelId;
|
|
46
|
-
for (const
|
|
47
|
-
if (
|
|
48
|
-
|
|
73
|
+
for (const event of events) {
|
|
74
|
+
if (options?.maxSeq !== void 0 && event.seq > options.maxSeq) break;
|
|
75
|
+
if (event.data.type === "unknown") {
|
|
76
|
+
throw new Error(
|
|
77
|
+
`Unsupported conversation event "${event.data.originalType}" at seq ${event.seq} (schema version ${event.schemaVersion})`
|
|
78
|
+
);
|
|
49
79
|
}
|
|
50
|
-
if (
|
|
51
|
-
modelProfile =
|
|
52
|
-
modelId =
|
|
80
|
+
if (event.data.type === "compaction" || event.data.type === "handoff" || event.data.type === "rollback") {
|
|
81
|
+
modelProfile = event.data.modelProfile;
|
|
82
|
+
modelId = event.data.modelId;
|
|
83
|
+
for (const replacement of event.data.replacementHistory) {
|
|
84
|
+
for (const message of durableMessages(replacement.message)) {
|
|
85
|
+
messages.push(message);
|
|
86
|
+
provenance.push(replacement.provenance ?? contextProvenance);
|
|
87
|
+
seqs.push(replacement.sourceEventSeq ?? event.seq);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
53
90
|
continue;
|
|
54
91
|
}
|
|
55
|
-
if (
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
92
|
+
if (event.data.type === "agent_step") {
|
|
93
|
+
for (const message of durableMessages(event.data.message)) {
|
|
94
|
+
messages.push(message);
|
|
95
|
+
provenance.push(messageEventProvenance(event.data));
|
|
96
|
+
seqs.push(event.seq);
|
|
97
|
+
}
|
|
59
98
|
continue;
|
|
60
99
|
}
|
|
61
|
-
if (
|
|
100
|
+
if (event.data.type === "authorization_completed") {
|
|
62
101
|
messages.push(
|
|
63
|
-
authorizationObservationMessage(
|
|
102
|
+
authorizationObservationMessage(event.data, event.createdAtMs)
|
|
64
103
|
);
|
|
65
104
|
provenance.push(contextProvenance);
|
|
66
|
-
seqs.push(
|
|
105
|
+
seqs.push(event.seq);
|
|
67
106
|
}
|
|
68
107
|
}
|
|
69
108
|
return { messages, provenance, seqs, modelProfile, modelId };
|
|
70
109
|
}
|
|
71
|
-
|
|
110
|
+
|
|
111
|
+
// src/chat/conversations/projection.ts
|
|
112
|
+
function connectedMcpProvidersFromEvents(events) {
|
|
72
113
|
const providers = /* @__PURE__ */ new Set();
|
|
73
|
-
for (const
|
|
74
|
-
if (
|
|
75
|
-
providers.add(
|
|
114
|
+
for (const event of events) {
|
|
115
|
+
if (event.data.type === "mcp_provider_connected") {
|
|
116
|
+
providers.add(event.data.provider);
|
|
76
117
|
}
|
|
77
118
|
}
|
|
78
119
|
return [...providers].sort((left, right) => left.localeCompare(right));
|
|
@@ -89,6 +130,11 @@ function countMatchingPrefix(left, right) {
|
|
|
89
130
|
}
|
|
90
131
|
return limit;
|
|
91
132
|
}
|
|
133
|
+
function normalizeDurableMessage(message) {
|
|
134
|
+
return piMessageSchema.parse(
|
|
135
|
+
JSON.parse(JSON.stringify(sanitizePostgresJson(message)))
|
|
136
|
+
);
|
|
137
|
+
}
|
|
92
138
|
function resolveCommitProvenance(args) {
|
|
93
139
|
if (args.explicitProvenance) {
|
|
94
140
|
if (args.explicitProvenance.length !== args.nextMessages.length) {
|
|
@@ -127,150 +173,136 @@ function resolveCommitProvenance(args) {
|
|
|
127
173
|
}
|
|
128
174
|
return provenance;
|
|
129
175
|
}
|
|
130
|
-
async function importLegacyIfNeeded(args) {
|
|
131
|
-
await ensureLegacyConversationImport({ conversationId: args.conversationId });
|
|
132
|
-
}
|
|
133
176
|
async function loadProjection(args) {
|
|
134
|
-
await
|
|
135
|
-
|
|
136
|
-
|
|
177
|
+
const events = await getConversationEventStore().loadCurrentHistory(
|
|
178
|
+
args.conversationId
|
|
179
|
+
);
|
|
180
|
+
return projectConversationEvents(events).messages;
|
|
137
181
|
}
|
|
138
182
|
async function loadConversationProjection(args) {
|
|
139
|
-
await
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
return
|
|
183
|
+
const events = await getConversationEventStore().loadCurrentHistory(
|
|
184
|
+
args.conversationId
|
|
185
|
+
);
|
|
186
|
+
return projectConversationEvents(events);
|
|
143
187
|
}
|
|
144
188
|
async function openConversationProjection(args) {
|
|
145
|
-
await
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
if (steps.some(
|
|
150
|
-
(step) => step.entry.type === "context_epoch_started" || step.entry.type === "pi_message"
|
|
151
|
-
)) {
|
|
152
|
-
return projection;
|
|
153
|
-
}
|
|
154
|
-
await stepStore.startEpoch(args.conversationId, {
|
|
155
|
-
reason: "initial",
|
|
156
|
-
modelProfile: "standard",
|
|
157
|
-
modelId: args.modelId,
|
|
158
|
-
messages: []
|
|
159
|
-
});
|
|
160
|
-
return {
|
|
161
|
-
messages: projection.messages,
|
|
162
|
-
provenance: projection.provenance,
|
|
163
|
-
modelProfile: "standard",
|
|
164
|
-
modelId: args.modelId
|
|
165
|
-
};
|
|
189
|
+
const events = await getConversationEventStore().loadCurrentHistory(
|
|
190
|
+
args.conversationId
|
|
191
|
+
);
|
|
192
|
+
return projectConversationEvents(events);
|
|
166
193
|
}
|
|
167
194
|
async function loadTurnProjection(args) {
|
|
168
|
-
|
|
169
|
-
const stepStore = getAgentStepStore();
|
|
195
|
+
const eventStore = getConversationEventStore();
|
|
170
196
|
if (args.committedSeq < 0) {
|
|
171
|
-
return
|
|
197
|
+
return projectConversationEvents(
|
|
198
|
+
await eventStore.loadCurrentHistory(args.conversationId)
|
|
199
|
+
);
|
|
172
200
|
}
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
201
|
+
const historyEvents = await eventStore.loadHistoryContaining(
|
|
202
|
+
args.conversationId,
|
|
203
|
+
args.committedSeq,
|
|
204
|
+
args.includeTail ? void 0 : args.committedSeq
|
|
205
|
+
);
|
|
206
|
+
if (!historyEvents) {
|
|
176
207
|
return void 0;
|
|
177
208
|
}
|
|
178
|
-
|
|
179
|
-
(step) => step.contextEpoch === committedStep.contextEpoch
|
|
180
|
-
);
|
|
181
|
-
return args.includeTail ? projectSteps(epochSteps) : projectSteps(epochSteps, { maxSeq: args.committedSeq });
|
|
209
|
+
return projectConversationEvents(historyEvents);
|
|
182
210
|
}
|
|
183
211
|
async function loadConnectedMcpProviders(args) {
|
|
184
|
-
await
|
|
185
|
-
|
|
186
|
-
|
|
212
|
+
const events = await getConversationEventStore().loadCurrentHistory(
|
|
213
|
+
args.conversationId
|
|
214
|
+
);
|
|
215
|
+
return connectedMcpProvidersFromEvents(events);
|
|
187
216
|
}
|
|
188
217
|
function messageTimestamp(message) {
|
|
189
218
|
const timestamp = message.timestamp;
|
|
190
219
|
return typeof timestamp === "number" ? timestamp : Date.now();
|
|
191
220
|
}
|
|
192
221
|
async function commitMessages(args) {
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
222
|
+
const executor = args.executor ?? getSqlExecutor();
|
|
223
|
+
return await withConversationEventLock(
|
|
224
|
+
executor,
|
|
225
|
+
args.conversationId,
|
|
226
|
+
async () => executor.transaction(
|
|
227
|
+
async () => await commitMessagesLocked(args, executor)
|
|
228
|
+
)
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
async function commitMessagesLocked(args, executor) {
|
|
232
|
+
const eventStore = createSqlConversationEventStore(executor);
|
|
233
|
+
const currentEvents = await eventStore.loadCurrentHistory(
|
|
234
|
+
args.conversationId
|
|
235
|
+
);
|
|
236
|
+
const current = projectConversationEvents(currentEvents);
|
|
237
|
+
const nextLocalMessages = stripRuntimeTurnContext(args.messages).map(
|
|
238
|
+
normalizeDurableMessage
|
|
239
|
+
);
|
|
240
|
+
const matchingPrefix = countMatchingPrefix(
|
|
241
|
+
current.messages,
|
|
242
|
+
nextLocalMessages
|
|
243
|
+
);
|
|
244
|
+
const nextLocalProvenance = resolveCommitProvenance({
|
|
245
|
+
existing: current,
|
|
246
|
+
nextMessages: nextLocalMessages,
|
|
200
247
|
matchingPrefix,
|
|
201
248
|
...args.provenance ? { explicitProvenance: args.provenance } : {},
|
|
202
249
|
...args.trailingMessageProvenance ? { trailingMessageProvenance: args.trailingMessageProvenance } : {},
|
|
203
250
|
...args.newMessageProvenance ? { newMessageProvenance: args.newMessageProvenance } : {}
|
|
204
251
|
});
|
|
205
|
-
if (
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
modelProfile: "standard",
|
|
209
|
-
modelId: args.modelId,
|
|
210
|
-
messages: args.messages.map((message, index) => ({
|
|
211
|
-
message,
|
|
212
|
-
createdAtMs: messageTimestamp(message),
|
|
213
|
-
provenance: nextProvenance[index]
|
|
214
|
-
}))
|
|
215
|
-
});
|
|
216
|
-
} else if (matchingPrefix === existing.messages.length) {
|
|
217
|
-
const newMessages = args.messages.slice(matchingPrefix);
|
|
218
|
-
await stepStore.append(
|
|
252
|
+
if (matchingPrefix === current.messages.length) {
|
|
253
|
+
const newMessages = nextLocalMessages.slice(matchingPrefix);
|
|
254
|
+
await eventStore.append(
|
|
219
255
|
args.conversationId,
|
|
220
256
|
newMessages.map((message, index) => ({
|
|
221
|
-
|
|
222
|
-
type: "
|
|
257
|
+
data: {
|
|
258
|
+
type: "agent_step",
|
|
223
259
|
message,
|
|
224
|
-
provenance:
|
|
260
|
+
provenance: nextLocalProvenance[matchingPrefix + index]
|
|
225
261
|
},
|
|
226
262
|
createdAtMs: messageTimestamp(message)
|
|
227
263
|
}))
|
|
228
264
|
);
|
|
229
265
|
} else {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
modelId: args.modelId,
|
|
234
|
-
messages: args.messages.map((message, index) => ({
|
|
235
|
-
message,
|
|
236
|
-
createdAtMs: messageTimestamp(message),
|
|
237
|
-
provenance: nextProvenance[index]
|
|
238
|
-
}))
|
|
239
|
-
});
|
|
266
|
+
throw new Error(
|
|
267
|
+
`Agent history for ${args.conversationId} changed before its committed boundary`
|
|
268
|
+
);
|
|
240
269
|
}
|
|
241
|
-
const
|
|
242
|
-
|
|
270
|
+
const committedEvents = await eventStore.loadCurrentHistory(
|
|
271
|
+
args.conversationId
|
|
243
272
|
);
|
|
273
|
+
const committed = projectConversationEvents(committedEvents);
|
|
244
274
|
return {
|
|
245
|
-
committedSeq:
|
|
275
|
+
committedSeq: committedEvents.at(-1)?.seq ?? -1,
|
|
276
|
+
historyVersion: committedEvents.at(-1)?.historyVersion ?? 0,
|
|
246
277
|
messageSeqs: committed.seqs,
|
|
247
|
-
|
|
278
|
+
messages: nextLocalMessages,
|
|
279
|
+
provenance: nextLocalProvenance
|
|
248
280
|
};
|
|
249
281
|
}
|
|
250
282
|
async function recordMcpProviderConnected(args) {
|
|
251
|
-
const
|
|
252
|
-
const
|
|
253
|
-
if (
|
|
283
|
+
const eventStore = getConversationEventStore();
|
|
284
|
+
const events = await eventStore.loadCurrentHistory(args.conversationId);
|
|
285
|
+
if (connectedMcpProvidersFromEvents(events).includes(args.provider)) {
|
|
254
286
|
return;
|
|
255
287
|
}
|
|
256
|
-
await
|
|
288
|
+
await eventStore.append(args.conversationId, [
|
|
257
289
|
{
|
|
258
|
-
|
|
290
|
+
data: { type: "mcp_provider_connected", provider: args.provider },
|
|
259
291
|
createdAtMs: Date.now()
|
|
260
292
|
}
|
|
261
293
|
]);
|
|
262
294
|
}
|
|
263
295
|
async function recordAuthorizationRequested(args) {
|
|
264
|
-
const
|
|
265
|
-
const
|
|
266
|
-
if (
|
|
267
|
-
(
|
|
296
|
+
const eventStore = getConversationEventStore();
|
|
297
|
+
const events = await eventStore.loadCurrentHistory(args.conversationId);
|
|
298
|
+
if (events.some(
|
|
299
|
+
(event) => event.data.type === "authorization_requested" && event.data.authorizationId === args.authorizationId
|
|
268
300
|
)) {
|
|
269
301
|
return;
|
|
270
302
|
}
|
|
271
|
-
await
|
|
303
|
+
await eventStore.append(args.conversationId, [
|
|
272
304
|
{
|
|
273
|
-
|
|
305
|
+
data: {
|
|
274
306
|
type: "authorization_requested",
|
|
275
307
|
kind: args.kind,
|
|
276
308
|
provider: args.provider,
|
|
@@ -283,16 +315,16 @@ async function recordAuthorizationRequested(args) {
|
|
|
283
315
|
]);
|
|
284
316
|
}
|
|
285
317
|
async function recordAuthorizationCompleted(args) {
|
|
286
|
-
const
|
|
287
|
-
const
|
|
288
|
-
if (
|
|
289
|
-
(
|
|
318
|
+
const eventStore = getConversationEventStore();
|
|
319
|
+
const events = await eventStore.loadCurrentHistory(args.conversationId);
|
|
320
|
+
if (events.some(
|
|
321
|
+
(event) => event.data.type === "authorization_completed" && event.data.authorizationId === args.authorizationId
|
|
290
322
|
)) {
|
|
291
323
|
return;
|
|
292
324
|
}
|
|
293
|
-
await
|
|
325
|
+
await eventStore.append(args.conversationId, [
|
|
294
326
|
{
|
|
295
|
-
|
|
327
|
+
data: {
|
|
296
328
|
type: "authorization_completed",
|
|
297
329
|
kind: args.kind,
|
|
298
330
|
provider: args.provider,
|
|
@@ -304,107 +336,132 @@ async function recordAuthorizationCompleted(args) {
|
|
|
304
336
|
]);
|
|
305
337
|
}
|
|
306
338
|
async function recordToolExecutionStarted(args) {
|
|
307
|
-
await
|
|
339
|
+
await getConversationEventStore().append(args.conversationId, [
|
|
308
340
|
{
|
|
309
|
-
|
|
341
|
+
data: {
|
|
310
342
|
type: "tool_execution_started",
|
|
311
343
|
toolCallId: args.toolCallId,
|
|
312
|
-
toolName: args.toolName
|
|
313
|
-
...args.args !== void 0 ? { args: args.args } : {}
|
|
344
|
+
toolName: args.toolName
|
|
314
345
|
},
|
|
315
346
|
createdAtMs: args.createdAtMs ?? Date.now()
|
|
316
347
|
}
|
|
317
348
|
]);
|
|
318
349
|
}
|
|
319
350
|
|
|
320
|
-
// src/chat/
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
(value) => typeof value === "number" && Number.isFinite(value)
|
|
340
|
-
))
|
|
341
|
-
);
|
|
342
|
-
}
|
|
343
|
-
function getFiniteCount(value) {
|
|
344
|
-
return typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.floor(value)) : void 0;
|
|
345
|
-
}
|
|
346
|
-
function getFiniteCost(value) {
|
|
347
|
-
return typeof value === "number" && Number.isFinite(value) ? Math.max(0, value) : void 0;
|
|
351
|
+
// src/chat/state/conversation.ts
|
|
352
|
+
function defaultConversationState() {
|
|
353
|
+
const nowMs = Date.now();
|
|
354
|
+
return {
|
|
355
|
+
schemaVersion: 1,
|
|
356
|
+
messages: [],
|
|
357
|
+
compactions: [],
|
|
358
|
+
backfill: {},
|
|
359
|
+
processing: {},
|
|
360
|
+
stats: {
|
|
361
|
+
estimatedContextTokens: 0,
|
|
362
|
+
totalMessageCount: 0,
|
|
363
|
+
compactedMessageCount: 0,
|
|
364
|
+
updatedAtMs: nowMs
|
|
365
|
+
},
|
|
366
|
+
vision: {
|
|
367
|
+
byFileId: {}
|
|
368
|
+
}
|
|
369
|
+
};
|
|
348
370
|
}
|
|
349
|
-
function
|
|
350
|
-
|
|
371
|
+
function coercePendingAuthState(value) {
|
|
372
|
+
if (!isRecord(value)) {
|
|
373
|
+
return void 0;
|
|
374
|
+
}
|
|
375
|
+
const kind = value.kind;
|
|
376
|
+
const provider = toOptionalString(value.provider);
|
|
377
|
+
const actorId = toOptionalString(value.actorId);
|
|
378
|
+
const authSessionId = toOptionalString(value.authSessionId);
|
|
379
|
+
const scope = toOptionalString(value.scope);
|
|
380
|
+
const sessionId = toOptionalString(value.sessionId);
|
|
381
|
+
const linkSentAtMs = toOptionalNumber(value.linkSentAtMs);
|
|
382
|
+
if (kind !== "mcp" && kind !== "plugin" || !provider || !actorId || kind === "mcp" && !authSessionId || !sessionId || typeof linkSentAtMs !== "number") {
|
|
383
|
+
return void 0;
|
|
384
|
+
}
|
|
385
|
+
const base = {
|
|
386
|
+
provider,
|
|
387
|
+
actorId,
|
|
388
|
+
...scope ? { scope } : {},
|
|
389
|
+
sessionId,
|
|
390
|
+
linkSentAtMs
|
|
391
|
+
};
|
|
392
|
+
return kind === "mcp" ? { ...base, authSessionId, kind } : { ...base, kind };
|
|
351
393
|
}
|
|
352
|
-
function
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
const value = getFiniteCount(usage[field]);
|
|
356
|
-
if (value === void 0) continue;
|
|
357
|
-
total = (total ?? 0) + value;
|
|
394
|
+
function coerceThreadConversationState(value) {
|
|
395
|
+
if (!isRecord(value)) {
|
|
396
|
+
return defaultConversationState();
|
|
358
397
|
}
|
|
359
|
-
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
const
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
398
|
+
const root = value;
|
|
399
|
+
const rawConversation = isRecord(root.conversation) ? root.conversation : {};
|
|
400
|
+
const base = defaultConversationState();
|
|
401
|
+
const messages = [];
|
|
402
|
+
const compactions = [];
|
|
403
|
+
const rawBackfill = isRecord(rawConversation.backfill) ? rawConversation.backfill : {};
|
|
404
|
+
const backfill = {
|
|
405
|
+
completedAtMs: toOptionalNumber(rawBackfill.completedAtMs),
|
|
406
|
+
source: rawBackfill.source === "recent_messages" || rawBackfill.source === "thread_fetch" ? rawBackfill.source : void 0
|
|
407
|
+
};
|
|
408
|
+
const rawProcessing = isRecord(rawConversation.processing) ? rawConversation.processing : {};
|
|
409
|
+
const processing = {
|
|
410
|
+
activeTurnId: toOptionalString(rawProcessing.activeTurnId),
|
|
411
|
+
lastCompletedAtMs: toOptionalNumber(rawProcessing.lastCompletedAtMs),
|
|
412
|
+
pendingAuth: coercePendingAuthState(rawProcessing.pendingAuth)
|
|
413
|
+
};
|
|
414
|
+
const rawStats = isRecord(rawConversation.stats) ? rawConversation.stats : {};
|
|
415
|
+
const stats = {
|
|
416
|
+
estimatedContextTokens: toOptionalNumber(rawStats.estimatedContextTokens) ?? base.stats.estimatedContextTokens,
|
|
417
|
+
totalMessageCount: toOptionalNumber(rawStats.totalMessageCount) ?? messages.length,
|
|
418
|
+
compactedMessageCount: toOptionalNumber(rawStats.compactedMessageCount) ?? 0,
|
|
419
|
+
updatedAtMs: toOptionalNumber(rawStats.updatedAtMs) ?? base.stats.updatedAtMs
|
|
420
|
+
};
|
|
421
|
+
const rawVision = isRecord(rawConversation.vision) ? rawConversation.vision : {};
|
|
422
|
+
const rawVisionByFileId = isRecord(rawVision.byFileId) ? rawVision.byFileId : {};
|
|
423
|
+
const byFileId = {};
|
|
424
|
+
for (const [fileId, value2] of Object.entries(rawVisionByFileId)) {
|
|
425
|
+
if (typeof fileId !== "string" || fileId.trim().length === 0) continue;
|
|
426
|
+
if (!isRecord(value2)) continue;
|
|
427
|
+
const summary = toOptionalString(value2.summary);
|
|
428
|
+
const analyzedAtMs = toOptionalNumber(value2.analyzedAtMs);
|
|
429
|
+
if (!summary || !analyzedAtMs) continue;
|
|
430
|
+
byFileId[fileId] = {
|
|
431
|
+
summary,
|
|
432
|
+
analyzedAtMs
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
return {
|
|
436
|
+
schemaVersion: 1,
|
|
437
|
+
messages,
|
|
438
|
+
compactions,
|
|
439
|
+
backfill,
|
|
440
|
+
processing,
|
|
441
|
+
stats,
|
|
442
|
+
vision: {
|
|
443
|
+
backfillCompletedAtMs: toOptionalNumber(rawVision.backfillCompletedAtMs),
|
|
444
|
+
byFileId
|
|
379
445
|
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
function buildConversationStatePatch(conversation) {
|
|
449
|
+
const {
|
|
450
|
+
compactions: _compactions,
|
|
451
|
+
messages: _messages,
|
|
452
|
+
...scratch
|
|
453
|
+
} = conversation;
|
|
454
|
+
return {
|
|
455
|
+
conversation: {
|
|
456
|
+
...scratch,
|
|
457
|
+
schemaVersion: 1,
|
|
458
|
+
stats: {
|
|
459
|
+
...conversation.stats,
|
|
460
|
+
totalMessageCount: conversation.messages.length,
|
|
461
|
+
updatedAtMs: Date.now()
|
|
387
462
|
}
|
|
388
|
-
continue;
|
|
389
|
-
}
|
|
390
|
-
const totalTokens = getFiniteCount(usage.totalTokens);
|
|
391
|
-
if (totalTokens !== void 0) {
|
|
392
|
-
totalOnlyTokens = (totalOnlyTokens ?? 0) + totalTokens;
|
|
393
463
|
}
|
|
394
|
-
}
|
|
395
|
-
if (totalOnlyTokens !== void 0) {
|
|
396
|
-
return {
|
|
397
|
-
totalTokens: totalOnlyTokens + (componentTotal ?? 0),
|
|
398
|
-
...reasoningTokens !== void 0 ? { reasoningTokens } : {},
|
|
399
|
-
...Object.keys(cost).length > 0 ? { cost } : {}
|
|
400
|
-
};
|
|
401
|
-
}
|
|
402
|
-
const result = {
|
|
403
|
-
...components,
|
|
404
|
-
...reasoningTokens !== void 0 ? { reasoningTokens } : {},
|
|
405
|
-
...Object.keys(cost).length > 0 ? { cost } : {}
|
|
406
464
|
};
|
|
407
|
-
return hasAgentTurnUsage(result) ? result : void 0;
|
|
408
465
|
}
|
|
409
466
|
|
|
410
467
|
// src/chat/state/turn-session.ts
|
|
@@ -414,67 +471,74 @@ import {
|
|
|
414
471
|
destinationSchema,
|
|
415
472
|
sourceSchema
|
|
416
473
|
} from "@sentry/junior-plugin-api";
|
|
417
|
-
import { z } from "zod";
|
|
474
|
+
import { z as z2 } from "zod";
|
|
475
|
+
|
|
476
|
+
// src/chat/state/turn-session-keys.ts
|
|
418
477
|
var AGENT_TURN_SESSION_PREFIX = "junior:agent_turn_session";
|
|
478
|
+
function agentTurnSessionKey(conversationId, sessionId) {
|
|
479
|
+
return `${AGENT_TURN_SESSION_PREFIX}:${conversationId}:${sessionId}`;
|
|
480
|
+
}
|
|
481
|
+
function agentTurnSessionConversationIndexKey(conversationId) {
|
|
482
|
+
return `${AGENT_TURN_SESSION_PREFIX}:conversation:${conversationId}:index`;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// src/chat/state/turn-session.ts
|
|
419
486
|
var AGENT_TURN_SESSION_INDEX_KEY = `${AGENT_TURN_SESSION_PREFIX}:index`;
|
|
420
487
|
var AGENT_TURN_SESSION_INDEX_MAX_LENGTH = 5e3;
|
|
421
488
|
var AGENT_TURN_SESSION_INDEX_READ_CONCURRENCY = 25;
|
|
422
489
|
var AGENT_TURN_SESSION_TTL_MS = THREAD_STATE_TTL_MS;
|
|
423
|
-
var agentTurnSessionStatusSchema =
|
|
490
|
+
var agentTurnSessionStatusSchema = z2.enum([
|
|
424
491
|
"running",
|
|
425
492
|
"awaiting_resume",
|
|
426
493
|
"completed",
|
|
427
494
|
"failed",
|
|
428
495
|
"abandoned"
|
|
429
496
|
]);
|
|
430
|
-
var agentTurnSurfaceSchema =
|
|
497
|
+
var agentTurnSurfaceSchema = z2.enum([
|
|
431
498
|
"slack",
|
|
432
499
|
"api",
|
|
433
500
|
"scheduler",
|
|
434
501
|
"internal"
|
|
435
502
|
]);
|
|
436
|
-
var agentTurnResumeReasonSchema =
|
|
503
|
+
var agentTurnResumeReasonSchema = z2.enum([
|
|
437
504
|
"timeout",
|
|
438
505
|
"auth",
|
|
439
|
-
"yield"
|
|
506
|
+
"yield",
|
|
507
|
+
"retry"
|
|
440
508
|
]);
|
|
441
|
-
var nonNegativeNumberSchema =
|
|
442
|
-
var seqCursorSchema =
|
|
443
|
-
var agentTurnSessionSummarySchema =
|
|
444
|
-
channelName:
|
|
445
|
-
version:
|
|
446
|
-
conversationId:
|
|
509
|
+
var nonNegativeNumberSchema = z2.number().finite().nonnegative();
|
|
510
|
+
var seqCursorSchema = z2.number().int().min(-1);
|
|
511
|
+
var agentTurnSessionSummarySchema = z2.object({
|
|
512
|
+
channelName: z2.string().min(1).optional(),
|
|
513
|
+
version: z2.number().int().nonnegative(),
|
|
514
|
+
conversationId: z2.string().min(1),
|
|
447
515
|
cumulativeDurationMs: nonNegativeNumberSchema,
|
|
448
516
|
cumulativeUsage: agentTurnUsageSchema.optional(),
|
|
449
517
|
destination: destinationSchema.optional(),
|
|
450
518
|
source: sourceSchema.optional(),
|
|
451
519
|
lastProgressAtMs: nonNegativeNumberSchema,
|
|
452
|
-
loadedSkillNames:
|
|
453
|
-
modelId:
|
|
454
|
-
reasoningLevel:
|
|
520
|
+
loadedSkillNames: z2.array(z2.string()).optional(),
|
|
521
|
+
modelId: z2.string().min(1).optional(),
|
|
522
|
+
reasoningLevel: z2.string().min(1).optional(),
|
|
455
523
|
actor: actorSchema.optional(),
|
|
456
524
|
resumeReason: agentTurnResumeReasonSchema.optional(),
|
|
457
|
-
resumedFromSliceId:
|
|
458
|
-
sessionId:
|
|
459
|
-
sliceId:
|
|
525
|
+
resumedFromSliceId: z2.number().int().nonnegative().optional(),
|
|
526
|
+
sessionId: z2.string().min(1),
|
|
527
|
+
sliceId: z2.number().int().nonnegative(),
|
|
460
528
|
startedAtMs: nonNegativeNumberSchema,
|
|
461
529
|
state: agentTurnSessionStatusSchema,
|
|
462
530
|
surface: agentTurnSurfaceSchema.optional(),
|
|
463
|
-
traceId:
|
|
531
|
+
traceId: z2.string().optional(),
|
|
464
532
|
updatedAtMs: nonNegativeNumberSchema
|
|
465
533
|
}).strict();
|
|
466
534
|
var storedAgentTurnSessionRecordSchema = agentTurnSessionSummarySchema.extend({
|
|
467
|
-
actors:
|
|
535
|
+
actors: z2.array(actorSchema).optional(),
|
|
468
536
|
committedSeq: seqCursorSchema,
|
|
469
|
-
|
|
470
|
-
|
|
537
|
+
historyVersion: z2.number().int().nonnegative().optional(),
|
|
538
|
+
errorMessage: z2.string().optional(),
|
|
539
|
+
turnStartSeq: seqCursorSchema.optional(),
|
|
540
|
+
runtimeContext: z2.array(piMessageSchema).optional()
|
|
471
541
|
}).strict();
|
|
472
|
-
function agentTurnSessionKey(conversationId, sessionId) {
|
|
473
|
-
return `${AGENT_TURN_SESSION_PREFIX}:${conversationId}:${sessionId}`;
|
|
474
|
-
}
|
|
475
|
-
function agentTurnSessionConversationIndexKey(conversationId) {
|
|
476
|
-
return `${AGENT_TURN_SESSION_PREFIX}:conversation:${conversationId}:index`;
|
|
477
|
-
}
|
|
478
542
|
function conversationExecutionFromSummary(summary) {
|
|
479
543
|
const status = summary.state === "completed" || summary.state === "abandoned" ? "idle" : summary.state;
|
|
480
544
|
return {
|
|
@@ -490,13 +554,6 @@ function parseAgentTurnSessionRecord(value) {
|
|
|
490
554
|
return storedAgentTurnSessionRecordSchema.parse(value);
|
|
491
555
|
}
|
|
492
556
|
function parseAgentTurnSessionSummary(value) {
|
|
493
|
-
if (typeof value === "object" && value !== null && !Array.isArray(value) && "requester" in value) {
|
|
494
|
-
const { requester, ...summary } = value;
|
|
495
|
-
return agentTurnSessionSummarySchema.parse({
|
|
496
|
-
...summary,
|
|
497
|
-
...summary.actor === void 0 ? { actor: requester } : {}
|
|
498
|
-
});
|
|
499
|
-
}
|
|
500
557
|
return agentTurnSessionSummarySchema.parse(value);
|
|
501
558
|
}
|
|
502
559
|
async function appendAgentTurnSessionSummary(summary, ttlMs) {
|
|
@@ -543,7 +600,8 @@ async function recordConversationActivityMetadata(args) {
|
|
|
543
600
|
visibility: args.destinationVisibility
|
|
544
601
|
});
|
|
545
602
|
}
|
|
546
|
-
function materializeAgentTurnSessionRecord(stored, piProjection, turnStartMessageIndex) {
|
|
603
|
+
function materializeAgentTurnSessionRecord(stored, piProjection, turnStartMessageIndex, restoreVolatileContext = true) {
|
|
604
|
+
const piMessages = restoreVolatileContext && (stored.state === "running" || stored.state === "awaiting_resume") ? restoreRuntimeContext(piProjection.messages, stored.runtimeContext) : piProjection.messages;
|
|
547
605
|
return {
|
|
548
606
|
version: stored.version,
|
|
549
607
|
...stored.channelName ? { channelName: stored.channelName } : {},
|
|
@@ -554,7 +612,7 @@ function materializeAgentTurnSessionRecord(stored, piProjection, turnStartMessag
|
|
|
554
612
|
startedAtMs: stored.startedAtMs,
|
|
555
613
|
lastProgressAtMs: stored.lastProgressAtMs,
|
|
556
614
|
updatedAtMs: stored.updatedAtMs,
|
|
557
|
-
piMessages
|
|
615
|
+
piMessages,
|
|
558
616
|
piMessageProvenance: piProjection.provenance,
|
|
559
617
|
actors: stored.actors ?? instructionActors(piProjection.provenance),
|
|
560
618
|
cumulativeDurationMs: stored.cumulativeDurationMs,
|
|
@@ -573,6 +631,30 @@ function materializeAgentTurnSessionRecord(stored, piProjection, turnStartMessag
|
|
|
573
631
|
...turnStartMessageIndex !== void 0 ? { turnStartMessageIndex } : {}
|
|
574
632
|
};
|
|
575
633
|
}
|
|
634
|
+
function restoreRuntimeContext(messages, runtimeContext) {
|
|
635
|
+
if (!runtimeContext || runtimeContext.length === 0) return messages;
|
|
636
|
+
const restored = [...messages];
|
|
637
|
+
for (const runtimeMessage of runtimeContext) {
|
|
638
|
+
const runtime = runtimeMessage;
|
|
639
|
+
const targetIndex = restored.findIndex((message) => {
|
|
640
|
+
const candidate = message;
|
|
641
|
+
return candidate.role === "user" && candidate.timestamp === runtime.timestamp;
|
|
642
|
+
});
|
|
643
|
+
if (targetIndex < 0) {
|
|
644
|
+
restored.push(runtimeMessage);
|
|
645
|
+
continue;
|
|
646
|
+
}
|
|
647
|
+
const target = restored[targetIndex];
|
|
648
|
+
restored[targetIndex] = {
|
|
649
|
+
...restored[targetIndex],
|
|
650
|
+
content: [
|
|
651
|
+
...Array.isArray(runtime.content) ? runtime.content : [],
|
|
652
|
+
...Array.isArray(target.content) ? target.content : []
|
|
653
|
+
]
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
return restored;
|
|
657
|
+
}
|
|
576
658
|
async function getStoredAgentTurnSessionRecord(conversationId, sessionId) {
|
|
577
659
|
const stateAdapter = getStateAdapter();
|
|
578
660
|
await stateAdapter.connect();
|
|
@@ -581,7 +663,7 @@ async function getStoredAgentTurnSessionRecord(conversationId, sessionId) {
|
|
|
581
663
|
);
|
|
582
664
|
return value == null ? void 0 : parseAgentTurnSessionRecord(value);
|
|
583
665
|
}
|
|
584
|
-
async function
|
|
666
|
+
async function materializeStoredAgentTurnSessionRecord(conversationId, sessionId, followCurrentReplacement) {
|
|
585
667
|
const parsed = await getStoredAgentTurnSessionRecord(
|
|
586
668
|
conversationId,
|
|
587
669
|
sessionId
|
|
@@ -589,21 +671,40 @@ async function getAgentTurnSessionRecord(conversationId, sessionId) {
|
|
|
589
671
|
if (!parsed) {
|
|
590
672
|
return void 0;
|
|
591
673
|
}
|
|
592
|
-
const
|
|
674
|
+
const pinnedProjection = await loadTurnProjection({
|
|
593
675
|
conversationId,
|
|
594
676
|
committedSeq: parsed.committedSeq,
|
|
595
677
|
// Unfinished records include the current-epoch tail so parked input
|
|
596
678
|
// appended after the last safe boundary stays model-visible on resume.
|
|
597
679
|
includeTail: parsed.state === "running" || parsed.state === "awaiting_resume"
|
|
598
680
|
});
|
|
599
|
-
if (!
|
|
681
|
+
if (!pinnedProjection) {
|
|
600
682
|
return void 0;
|
|
601
683
|
}
|
|
602
|
-
const
|
|
684
|
+
const currentHistory = await getConversationEventStore().loadCurrentHistory(conversationId);
|
|
685
|
+
const currentHistoryVersion = currentHistory.at(-1)?.historyVersion ?? parsed.historyVersion ?? 0;
|
|
686
|
+
const followsReplacement = followCurrentReplacement && (parsed.state === "running" || parsed.state === "awaiting_resume") && parsed.historyVersion !== void 0 && parsed.historyVersion !== currentHistoryVersion;
|
|
687
|
+
const piProjection = followsReplacement ? projectConversationEvents(currentHistory) : pinnedProjection;
|
|
688
|
+
const turnStartMessageIndex = followsReplacement ? 0 : parsed.turnStartSeq === void 0 ? void 0 : piProjection.seqs.filter((seq) => seq <= parsed.turnStartSeq).length;
|
|
603
689
|
return materializeAgentTurnSessionRecord(
|
|
604
690
|
parsed,
|
|
605
691
|
piProjection,
|
|
606
|
-
turnStartMessageIndex
|
|
692
|
+
turnStartMessageIndex,
|
|
693
|
+
!followsReplacement && (parsed.historyVersion === void 0 || parsed.historyVersion === currentHistoryVersion)
|
|
694
|
+
);
|
|
695
|
+
}
|
|
696
|
+
async function getAgentTurnSessionRecord(conversationId, sessionId) {
|
|
697
|
+
return await materializeStoredAgentTurnSessionRecord(
|
|
698
|
+
conversationId,
|
|
699
|
+
sessionId,
|
|
700
|
+
false
|
|
701
|
+
);
|
|
702
|
+
}
|
|
703
|
+
async function getAgentTurnSessionRecordForResume(conversationId, sessionId) {
|
|
704
|
+
return await materializeStoredAgentTurnSessionRecord(
|
|
705
|
+
conversationId,
|
|
706
|
+
sessionId,
|
|
707
|
+
true
|
|
607
708
|
);
|
|
608
709
|
}
|
|
609
710
|
function buildStoredRecord(args) {
|
|
@@ -619,7 +720,9 @@ function buildStoredRecord(args) {
|
|
|
619
720
|
lastProgressAtMs: args.lastProgressAtMs ?? nowMs,
|
|
620
721
|
updatedAtMs: nowMs,
|
|
621
722
|
committedSeq: args.committedSeq,
|
|
723
|
+
...args.historyVersion !== void 0 ? { historyVersion: args.historyVersion } : {},
|
|
622
724
|
...args.turnStartSeq !== void 0 ? { turnStartSeq: args.turnStartSeq } : {},
|
|
725
|
+
...args.runtimeContext && args.runtimeContext.length > 0 ? { runtimeContext: args.runtimeContext } : {},
|
|
623
726
|
cumulativeDurationMs: args.cumulativeDurationMs,
|
|
624
727
|
...args.cumulativeUsage ? { cumulativeUsage: args.cumulativeUsage } : {},
|
|
625
728
|
...args.destination ? { destination: args.destination } : {},
|
|
@@ -653,8 +756,10 @@ async function setStoredRecord(args) {
|
|
|
653
756
|
const {
|
|
654
757
|
actors: _actors,
|
|
655
758
|
committedSeq: _committedSeq,
|
|
759
|
+
historyVersion: _historyVersion,
|
|
656
760
|
errorMessage: _errorMessage,
|
|
657
761
|
turnStartSeq: _turnStartSeq,
|
|
762
|
+
runtimeContext: _runtimeContext,
|
|
658
763
|
...summary
|
|
659
764
|
} = args.record;
|
|
660
765
|
await appendAgentTurnSessionSummary(summary, args.ttlMs);
|
|
@@ -686,7 +791,9 @@ async function updateAgentTurnSessionState(args) {
|
|
|
686
791
|
sliceId: args.existing.sliceId,
|
|
687
792
|
state: args.state,
|
|
688
793
|
committedSeq: parsed.committedSeq,
|
|
794
|
+
...parsed.historyVersion !== void 0 ? { historyVersion: parsed.historyVersion } : {},
|
|
689
795
|
...parsed.turnStartSeq !== void 0 ? { turnStartSeq: parsed.turnStartSeq } : {},
|
|
796
|
+
...parsed.runtimeContext ? { runtimeContext: parsed.runtimeContext } : {},
|
|
690
797
|
...parsed.channelName ? { channelName: parsed.channelName } : {},
|
|
691
798
|
startedAtMs: parsed.startedAtMs,
|
|
692
799
|
lastProgressAtMs: parsed.lastProgressAtMs,
|
|
@@ -717,17 +824,21 @@ async function upsertAgentTurnSessionRecord(args) {
|
|
|
717
824
|
const instructionActor = args.actor ?? existingRecord?.actor;
|
|
718
825
|
const commit = await commitMessages({
|
|
719
826
|
conversationId: args.conversationId,
|
|
720
|
-
modelId: args.modelId,
|
|
721
827
|
messages: args.piMessages,
|
|
722
828
|
...instructionActor ? { newMessageProvenance: instructionProvenanceFor(instructionActor) } : {},
|
|
723
829
|
...args.trailingMessageProvenance ? { trailingMessageProvenance: args.trailingMessageProvenance } : {}
|
|
724
830
|
});
|
|
725
|
-
const
|
|
726
|
-
|
|
831
|
+
const durableTurnStartMessageIndex = args.turnStartMessageIndex === void 0 ? void 0 : stripRuntimeTurnContext(
|
|
832
|
+
args.piMessages.slice(0, args.turnStartMessageIndex)
|
|
833
|
+
).length;
|
|
834
|
+
const runtimeContext = retainRuntimeTurnContext(args.piMessages);
|
|
835
|
+
const retainedRuntimeContext = runtimeContext.length > 0 ? runtimeContext : existingRecord?.historyVersion === commit.historyVersion ? existingRecord.runtimeContext : void 0;
|
|
836
|
+
const turnStartSeq = durableTurnStartMessageIndex === void 0 ? existingRecord?.turnStartSeq : durableTurnStartMessageIndex <= 0 ? -1 : commit.messageSeqs[durableTurnStartMessageIndex - 1] ?? commit.committedSeq;
|
|
837
|
+
const turnStartMessageIndex = durableTurnStartMessageIndex ?? (turnStartSeq === void 0 ? void 0 : commit.messageSeqs.filter((seq) => seq <= turnStartSeq).length);
|
|
727
838
|
return await setStoredRecord({
|
|
728
839
|
conversationStore: args.conversationStore,
|
|
729
840
|
destinationVisibility: args.destinationVisibility,
|
|
730
|
-
piMessages:
|
|
841
|
+
piMessages: commit.messages,
|
|
731
842
|
piMessageProvenance: commit.provenance,
|
|
732
843
|
ttlMs,
|
|
733
844
|
...turnStartMessageIndex !== void 0 ? { turnStartMessageIndex } : {},
|
|
@@ -740,7 +851,9 @@ async function upsertAgentTurnSessionRecord(args) {
|
|
|
740
851
|
...existingRecord?.startedAtMs !== void 0 ? { startedAtMs: existingRecord.startedAtMs } : {},
|
|
741
852
|
...args.lastProgressAtMs !== void 0 ? { lastProgressAtMs: args.lastProgressAtMs } : {},
|
|
742
853
|
committedSeq: commit.committedSeq,
|
|
854
|
+
historyVersion: commit.historyVersion,
|
|
743
855
|
...turnStartSeq !== void 0 ? { turnStartSeq } : {},
|
|
856
|
+
...retainedRuntimeContext ? { runtimeContext: retainedRuntimeContext } : {},
|
|
744
857
|
previousVersion: existingRecord?.version,
|
|
745
858
|
cumulativeDurationMs: args.cumulativeDurationMs ?? existingRecord?.cumulativeDurationMs ?? 0,
|
|
746
859
|
...args.cumulativeUsage ? { cumulativeUsage: args.cumulativeUsage } : {},
|
|
@@ -917,8 +1030,11 @@ async function failAgentTurnSessionRecord(args) {
|
|
|
917
1030
|
});
|
|
918
1031
|
}
|
|
919
1032
|
|
|
1033
|
+
// src/chat/state/ttl.ts
|
|
1034
|
+
var JUNIOR_THREAD_STATE_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
1035
|
+
|
|
920
1036
|
export {
|
|
921
|
-
|
|
1037
|
+
piMessageSchema,
|
|
922
1038
|
loadProjection,
|
|
923
1039
|
loadConversationProjection,
|
|
924
1040
|
openConversationProjection,
|
|
@@ -928,14 +1044,18 @@ export {
|
|
|
928
1044
|
recordAuthorizationRequested,
|
|
929
1045
|
recordAuthorizationCompleted,
|
|
930
1046
|
recordToolExecutionStarted,
|
|
931
|
-
|
|
932
|
-
|
|
1047
|
+
AGENT_TURN_SESSION_PREFIX,
|
|
1048
|
+
agentTurnSessionKey,
|
|
1049
|
+
agentTurnSessionConversationIndexKey,
|
|
933
1050
|
getAgentTurnSessionRecord,
|
|
1051
|
+
getAgentTurnSessionRecordForResume,
|
|
934
1052
|
upsertAgentTurnSessionRecord,
|
|
935
1053
|
recordAgentTurnSessionSummary,
|
|
936
1054
|
listAgentTurnSessionSummariesForConversation,
|
|
937
|
-
listBoundedAgentTurnSessionSummariesForConversation,
|
|
938
1055
|
listAgentTurnSessionSummariesForConversations,
|
|
939
1056
|
abandonAgentTurnSessionRecord,
|
|
940
|
-
failAgentTurnSessionRecord
|
|
1057
|
+
failAgentTurnSessionRecord,
|
|
1058
|
+
JUNIOR_THREAD_STATE_TTL_MS,
|
|
1059
|
+
coerceThreadConversationState,
|
|
1060
|
+
buildConversationStatePatch
|
|
941
1061
|
};
|