@sentry/junior 0.112.0 → 0.114.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-6MVTPKP4.js → agent-hooks-WNBUY4OB.js} +8 -8
- package/dist/api/conversations/cursor.d.ts +17 -0
- package/dist/api/conversations/detail.d.ts +40 -18
- package/dist/api/conversations/event-list.d.ts +115 -0
- package/dist/api/conversations/event-page.d.ts +18 -0
- package/dist/api/conversations/events.d.ts +6 -2
- package/dist/api/conversations/projection.d.ts +6 -1
- package/dist/api/schema/conversation.d.ts +228 -51
- package/dist/api/schema.d.ts +2 -2
- package/dist/api/schema.js +7 -1
- package/dist/api.js +461 -139
- package/dist/app.d.ts +2 -0
- package/dist/app.js +33 -24
- package/dist/{catalog-runtime-UEO25P2J.js → catalog-runtime-6O4M6JGA.js} +5 -5
- package/dist/chat/config.d.ts +1 -1
- package/dist/chat/conversations/history.d.ts +86 -0
- package/dist/chat/conversations/projection.d.ts +20 -1
- package/dist/chat/pi/transcript.d.ts +2 -0
- package/dist/chat/services/context-budget.d.ts +7 -2
- package/dist/chat/services/context-compaction.d.ts +28 -1
- package/dist/chat/services/conversation-memory.d.ts +1 -0
- package/dist/chat/services/provider-error.d.ts +40 -0
- package/dist/chat/services/provider-retry.d.ts +3 -6
- package/dist/chat/services/turn-router.d.ts +1 -0
- package/dist/chat/task-execution/state.d.ts +2 -2
- package/dist/chat/task-execution/store.d.ts +1 -1
- package/dist/chat/tools/sandbox/edit-file.d.ts +1 -1
- package/dist/chat/tools/sandbox/text-edits.d.ts +1 -0
- package/dist/{chunk-CSS7JHEM.js → chunk-4FUEG3QY.js} +1 -1
- package/dist/{chunk-AU2JVUDF.js → chunk-5CZ7RETL.js} +1 -1
- package/dist/{chunk-SKEMI4IF.js → chunk-6QWPVTMO.js} +200 -52
- package/dist/{chunk-AWNDKI5K.js → chunk-ABPSDO6M.js} +20 -15
- package/dist/{chunk-QIALGHRN.js → chunk-FIGAF6KL.js} +34 -2
- package/dist/{chunk-TZU3R5OC.js → chunk-K2W4CK7K.js} +1 -1
- package/dist/{chunk-2FJ6WEYV.js → chunk-O4GT7LYB.js} +1 -1
- package/dist/{chunk-ZHP4KNF7.js → chunk-OSKEC4XU.js} +1 -1
- package/dist/{chunk-IV2O4HQJ.js → chunk-PM3PX42K.js} +1 -1
- package/dist/{chunk-NDQL4ESR.js → chunk-RD7EJI7H.js} +2 -2
- package/dist/{chunk-JE23YR3X.js → chunk-S4QDH23A.js} +75 -43
- package/dist/{chunk-GJG67YFS.js → chunk-TLGM5X2M.js} +2 -2
- package/dist/{chunk-VBSVNOLA.js → chunk-VNNBSKCO.js} +5 -5
- package/dist/{chunk-4EJO4HIC.js → chunk-W6RDUAO3.js} +1 -1
- package/dist/{chunk-GR4IB6OQ.js → chunk-WV4UJBAS.js} +431 -96
- package/dist/{chunk-66IP6WED.js → chunk-XLFBQJUO.js} +4 -4
- package/dist/{chunk-X3SP5RDW.js → chunk-YU6PO42Q.js} +1 -1
- package/dist/{chunk-PK4ETCUQ.js → chunk-ZGXH3REA.js} +226 -215
- package/dist/cli/chat.js +19 -19
- package/dist/cli/check.js +6 -6
- package/dist/cli/plugins.js +11 -11
- package/dist/cli/snapshot-warmup.js +8 -8
- package/dist/cli/upgrade.js +5 -5
- package/dist/{db-P5H5RVQV.js → db-4VLP7KBF.js} +5 -5
- package/dist/instrumentation.js +2 -2
- package/dist/nitro.js +2 -2
- package/dist/{runner-B4ZDUO3R.js → runner-IPXLWQOF.js} +12 -13
- package/dist/{skills-GWTOZ3XV.js → skills-QCNZISNF.js} +6 -6
- package/dist/{validation-QFIC6XH6.js → validation-I2BW3UHD.js} +6 -6
- package/dist/version.js +1 -1
- package/package.json +6 -6
|
@@ -1,18 +1,30 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CooperativeTurnYieldError,
|
|
3
3
|
JUNIOR_THREAD_STATE_TTL_MS,
|
|
4
|
+
TURN_CONTEXT_TAG,
|
|
4
5
|
TurnInputCommitLostError,
|
|
5
6
|
TurnSliceLimitExceededError,
|
|
6
7
|
abandonReplacedPendingAuth,
|
|
7
8
|
canReusePendingAuthLink,
|
|
8
9
|
estimateTextTokens,
|
|
10
|
+
extractAssistantText,
|
|
9
11
|
getAgentContextCompactionTriggerTokens,
|
|
12
|
+
getAgentContextInputLimitTokens,
|
|
10
13
|
getInterruptionMarker,
|
|
14
|
+
getPiMessageRole,
|
|
15
|
+
getTerminalAssistantMessages,
|
|
16
|
+
hasRuntimeTurnContext,
|
|
17
|
+
isAssistantMessage,
|
|
18
|
+
isContinuablePiBoundary,
|
|
19
|
+
isToolResultError,
|
|
20
|
+
isToolResultMessage,
|
|
11
21
|
isTurnInputCommitLostError,
|
|
12
22
|
loadConnectedMcpProviders,
|
|
13
23
|
loadConversationProjection,
|
|
24
|
+
loadTurnRoute,
|
|
14
25
|
loadTurnSessionRecord,
|
|
15
26
|
mergeArtifactsState,
|
|
27
|
+
normalizeToolNameFromResult,
|
|
16
28
|
openConversationProjection,
|
|
17
29
|
persistAuthPauseSessionRecord,
|
|
18
30
|
persistContinuationSessionRecord,
|
|
@@ -21,8 +33,12 @@ import {
|
|
|
21
33
|
recordAuthorizationRequested,
|
|
22
34
|
recordMcpProviderConnected,
|
|
23
35
|
recordToolExecutionStarted,
|
|
36
|
+
recordTurnRoute,
|
|
37
|
+
retainRuntimeTurnContext,
|
|
38
|
+
stripRuntimeTurnContext,
|
|
39
|
+
trimTrailingAssistantMessages,
|
|
24
40
|
updateConversationStats
|
|
25
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-6QWPVTMO.js";
|
|
26
42
|
import {
|
|
27
43
|
buildNonInteractiveShellScript,
|
|
28
44
|
createSandboxSession,
|
|
@@ -39,7 +55,7 @@ import {
|
|
|
39
55
|
runNonInteractiveCommand,
|
|
40
56
|
throwSandboxOperationError,
|
|
41
57
|
wrapSandboxSetupError
|
|
42
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-XLFBQJUO.js";
|
|
43
59
|
import {
|
|
44
60
|
addAgentTurnUsage,
|
|
45
61
|
hasAgentTurnUsage
|
|
@@ -56,7 +72,7 @@ import {
|
|
|
56
72
|
getPlugins,
|
|
57
73
|
getSlackToolContext,
|
|
58
74
|
resolveChannelCapabilities
|
|
59
|
-
} from "./chunk-
|
|
75
|
+
} from "./chunk-VNNBSKCO.js";
|
|
60
76
|
import {
|
|
61
77
|
SANDBOX_DATA_ROOT,
|
|
62
78
|
SANDBOX_SKILLS_ROOT,
|
|
@@ -65,7 +81,7 @@ import {
|
|
|
65
81
|
getStateAdapter,
|
|
66
82
|
sandboxSkillDir,
|
|
67
83
|
sandboxSkillFile
|
|
68
|
-
} from "./chunk-
|
|
84
|
+
} from "./chunk-YU6PO42Q.js";
|
|
69
85
|
import {
|
|
70
86
|
SlackActionError,
|
|
71
87
|
downloadPrivateSlackFile,
|
|
@@ -75,7 +91,7 @@ import {
|
|
|
75
91
|
isDmChannel,
|
|
76
92
|
normalizeSlackConversationId,
|
|
77
93
|
withSlackRetries
|
|
78
|
-
} from "./chunk-
|
|
94
|
+
} from "./chunk-RD7EJI7H.js";
|
|
79
95
|
import {
|
|
80
96
|
contextProvenance,
|
|
81
97
|
getConversationEventStore,
|
|
@@ -85,7 +101,7 @@ import {
|
|
|
85
101
|
instructionActors,
|
|
86
102
|
instructionProvenanceFor,
|
|
87
103
|
parseDestination
|
|
88
|
-
} from "./chunk-
|
|
104
|
+
} from "./chunk-FIGAF6KL.js";
|
|
89
105
|
import {
|
|
90
106
|
sleep
|
|
91
107
|
} from "./chunk-4ZNGQH7C.js";
|
|
@@ -99,36 +115,26 @@ import {
|
|
|
99
115
|
MODEL_HANDOFF_SUMMARY_PREFIX,
|
|
100
116
|
ModelProfileNotConfiguredError,
|
|
101
117
|
STANDARD_MODEL_PROFILE,
|
|
102
|
-
TURN_CONTEXT_TAG,
|
|
103
118
|
TURN_REASONING_LEVELS,
|
|
104
119
|
botConfig,
|
|
105
120
|
completeObject,
|
|
106
121
|
completeText,
|
|
122
|
+
createProviderError,
|
|
107
123
|
escapeXml,
|
|
108
|
-
extractAssistantText,
|
|
109
124
|
getGatewayApiKey,
|
|
110
125
|
getPiGatewayApiKey,
|
|
111
|
-
getTerminalAssistantMessages,
|
|
112
126
|
hasCompactedConversationContext,
|
|
113
|
-
hasRuntimeTurnContext,
|
|
114
|
-
isAssistantMessage,
|
|
115
127
|
isCompactionSummaryText,
|
|
116
128
|
isProviderRetryError,
|
|
117
|
-
isToolResultError,
|
|
118
|
-
isToolResultMessage,
|
|
119
129
|
modelIdForProfile,
|
|
120
130
|
modelProfileSchema,
|
|
121
|
-
nextProviderRetry,
|
|
122
131
|
normalizeSlackEmojiName,
|
|
123
|
-
|
|
132
|
+
parseTurnReasoningLevel,
|
|
124
133
|
profileConfig,
|
|
125
134
|
renderCurrentInstruction,
|
|
126
135
|
resolveGatewayModel,
|
|
127
|
-
retainRuntimeTurnContext,
|
|
128
|
-
stripRuntimeTurnContext,
|
|
129
|
-
trimTrailingAssistantMessages,
|
|
130
136
|
unwrapCurrentInstruction
|
|
131
|
-
} from "./chunk-
|
|
137
|
+
} from "./chunk-ZGXH3REA.js";
|
|
132
138
|
import {
|
|
133
139
|
parseSlackThreadId,
|
|
134
140
|
resolveConversationPrivacy,
|
|
@@ -144,17 +150,17 @@ import {
|
|
|
144
150
|
findSkillByName,
|
|
145
151
|
loadSkillsByName,
|
|
146
152
|
parseSkillInvocation
|
|
147
|
-
} from "./chunk-
|
|
153
|
+
} from "./chunk-TLGM5X2M.js";
|
|
148
154
|
import {
|
|
149
155
|
pluginCatalogRuntime
|
|
150
|
-
} from "./chunk-
|
|
156
|
+
} from "./chunk-OSKEC4XU.js";
|
|
151
157
|
import {
|
|
152
158
|
CredentialUnavailableError,
|
|
153
159
|
credentialContextSchema,
|
|
154
160
|
credentialUserSubjectId,
|
|
155
161
|
resolveAuthTokenPlaceholder,
|
|
156
162
|
resolvePluginCommandEnv
|
|
157
|
-
} from "./chunk-
|
|
163
|
+
} from "./chunk-K2W4CK7K.js";
|
|
158
164
|
import {
|
|
159
165
|
isUserActor
|
|
160
166
|
} from "./chunk-C4MZ3GP5.js";
|
|
@@ -175,7 +181,7 @@ import {
|
|
|
175
181
|
summarizeMessageText,
|
|
176
182
|
withLogContext,
|
|
177
183
|
withSpan
|
|
178
|
-
} from "./chunk-
|
|
184
|
+
} from "./chunk-4FUEG3QY.js";
|
|
179
185
|
import {
|
|
180
186
|
isRecord,
|
|
181
187
|
parseSlackChannelId,
|
|
@@ -274,7 +280,6 @@ function shouldPropagateSandboxEgressTrace(host, config = {}) {
|
|
|
274
280
|
|
|
275
281
|
// src/chat/agent/index.ts
|
|
276
282
|
import { Agent } from "@earendil-works/pi-agent-core";
|
|
277
|
-
import { isRetryableAssistantError } from "@earendil-works/pi-ai";
|
|
278
283
|
|
|
279
284
|
// src/chat/sandbox/skill-sandbox.ts
|
|
280
285
|
import fs from "fs/promises";
|
|
@@ -613,6 +618,9 @@ function shouldEmitDevAgentTrace() {
|
|
|
613
618
|
return process.env.NODE_ENV === "development";
|
|
614
619
|
}
|
|
615
620
|
|
|
621
|
+
// src/chat/services/turn-result.ts
|
|
622
|
+
import { isRetryableAssistantError } from "@earendil-works/pi-ai";
|
|
623
|
+
|
|
616
624
|
// src/chat/no-reply.ts
|
|
617
625
|
var NO_REPLY_MARKER = "[[NO_REPLY]]";
|
|
618
626
|
function isNoReplyMarker(text) {
|
|
@@ -827,7 +835,10 @@ function buildTurnResult(input) {
|
|
|
827
835
|
usage,
|
|
828
836
|
stopReason,
|
|
829
837
|
errorMessage,
|
|
830
|
-
providerError:
|
|
838
|
+
providerError: resolvedOutcome === "provider_error" && errorMessage ? createProviderError(errorMessage, {
|
|
839
|
+
modelId,
|
|
840
|
+
retryable: lastAssistant !== void 0 && isAssistantMessage(lastAssistant) && isRetryableAssistantError(lastAssistant)
|
|
841
|
+
}) : void 0
|
|
831
842
|
};
|
|
832
843
|
return {
|
|
833
844
|
text: primaryText,
|
|
@@ -838,6 +849,40 @@ function buildTurnResult(input) {
|
|
|
838
849
|
};
|
|
839
850
|
}
|
|
840
851
|
|
|
852
|
+
// src/chat/services/provider-retry.ts
|
|
853
|
+
import {
|
|
854
|
+
isRetryableAssistantError as isRetryableAssistantError2
|
|
855
|
+
} from "@earendil-works/pi-ai";
|
|
856
|
+
var PROVIDER_RETRY_DELAYS_MS = [2e3, 4e3, 8e3];
|
|
857
|
+
var MAX_PROVIDER_RETRY_DELAY_MS = 6e4;
|
|
858
|
+
function nextProviderRetry(args) {
|
|
859
|
+
const backoffMs = PROVIDER_RETRY_DELAYS_MS[args.attempt];
|
|
860
|
+
const errorMessage = args.failure?.errorMessage;
|
|
861
|
+
if (backoffMs === void 0 || !args.failure || !errorMessage) {
|
|
862
|
+
return void 0;
|
|
863
|
+
}
|
|
864
|
+
const providerError = createProviderError(errorMessage, {
|
|
865
|
+
retryable: true
|
|
866
|
+
});
|
|
867
|
+
const hasRetrySignal = isRetryableAssistantError2(args.failure) || providerError.status === 408;
|
|
868
|
+
if (!hasRetrySignal || !providerError.retryable) {
|
|
869
|
+
return void 0;
|
|
870
|
+
}
|
|
871
|
+
const delayMs = Math.min(
|
|
872
|
+
MAX_PROVIDER_RETRY_DELAY_MS,
|
|
873
|
+
Math.max(backoffMs, providerError.retryAfterMs ?? 0)
|
|
874
|
+
);
|
|
875
|
+
const messages = trimTrailingAssistantMessages(args.messages);
|
|
876
|
+
if (messages.length === args.messages.length) {
|
|
877
|
+
return void 0;
|
|
878
|
+
}
|
|
879
|
+
const tailRole = getPiMessageRole(messages.at(-1));
|
|
880
|
+
if (tailRole !== "user" && tailRole !== "toolResult") {
|
|
881
|
+
return void 0;
|
|
882
|
+
}
|
|
883
|
+
return { delayMs, messages };
|
|
884
|
+
}
|
|
885
|
+
|
|
841
886
|
// src/chat/tool-support/structured-result.ts
|
|
842
887
|
import { z } from "zod";
|
|
843
888
|
var juniorToolContinuationSchema = z.object({
|
|
@@ -1057,7 +1102,8 @@ function configuredTurnRoute(profile, reasoningLevel, source) {
|
|
|
1057
1102
|
return {
|
|
1058
1103
|
profile,
|
|
1059
1104
|
reasoningLevel,
|
|
1060
|
-
reason: `configured:${source}
|
|
1105
|
+
reason: `configured:${source}`,
|
|
1106
|
+
source: source === "profile" ? "inherited" : "configured"
|
|
1061
1107
|
};
|
|
1062
1108
|
}
|
|
1063
1109
|
async function selectTurnRoute(args) {
|
|
@@ -1117,7 +1163,7 @@ async function selectTurnRoute(args) {
|
|
|
1117
1163
|
"gen_ai.request.reasoning.level_confidence": normalizedSelection.confidence
|
|
1118
1164
|
} : {}
|
|
1119
1165
|
});
|
|
1120
|
-
return normalizedSelection;
|
|
1166
|
+
return { ...normalizedSelection, source: "router" };
|
|
1121
1167
|
}
|
|
1122
1168
|
);
|
|
1123
1169
|
}
|
|
@@ -1163,20 +1209,37 @@ async function classifyTurn(args) {
|
|
|
1163
1209
|
confidence: parsed.confidence,
|
|
1164
1210
|
profile: STANDARD_MODEL_PROFILE,
|
|
1165
1211
|
reasoningLevel: CLASSIFIER_FALLBACK_REASONING_LEVEL,
|
|
1166
|
-
reason: `low_confidence_medium_default:${reason}
|
|
1212
|
+
reason: `low_confidence_medium_default:${reason}`,
|
|
1213
|
+
source: "router"
|
|
1167
1214
|
};
|
|
1168
1215
|
}
|
|
1169
1216
|
return {
|
|
1170
1217
|
confidence: parsed.confidence,
|
|
1171
1218
|
profile: parsed.profile,
|
|
1172
1219
|
reasoningLevel: parsed.reasoning_level,
|
|
1173
|
-
reason
|
|
1220
|
+
reason,
|
|
1221
|
+
source: "router"
|
|
1174
1222
|
};
|
|
1175
|
-
} catch {
|
|
1223
|
+
} catch (error) {
|
|
1224
|
+
logWarn(
|
|
1225
|
+
"turn_router_classifier_failed",
|
|
1226
|
+
{
|
|
1227
|
+
messageConversationId: args.metadata.threadId,
|
|
1228
|
+
destinationName: args.metadata.channelId,
|
|
1229
|
+
userId: args.metadata.actorId,
|
|
1230
|
+
runId: args.metadata.runId,
|
|
1231
|
+
modelId: args.fastModelId
|
|
1232
|
+
},
|
|
1233
|
+
{
|
|
1234
|
+
"exception.message": error instanceof Error ? error.message : String(error)
|
|
1235
|
+
},
|
|
1236
|
+
"Turn router classifier failed; using the default route"
|
|
1237
|
+
);
|
|
1176
1238
|
return {
|
|
1177
1239
|
profile: STANDARD_MODEL_PROFILE,
|
|
1178
1240
|
reasoningLevel: CLASSIFIER_FALLBACK_REASONING_LEVEL,
|
|
1179
|
-
reason: "classifier_error_default"
|
|
1241
|
+
reason: "classifier_error_default",
|
|
1242
|
+
source: "router"
|
|
1180
1243
|
};
|
|
1181
1244
|
}
|
|
1182
1245
|
}
|
|
@@ -5066,6 +5129,16 @@ async function collectFiles(params) {
|
|
|
5066
5129
|
}
|
|
5067
5130
|
|
|
5068
5131
|
// src/chat/tools/sandbox/text-edits.ts
|
|
5132
|
+
var MAX_DIFF_LINE_CHARS = 4e3;
|
|
5133
|
+
function truncateDiffLine(value) {
|
|
5134
|
+
if (value.length <= MAX_DIFF_LINE_CHARS) {
|
|
5135
|
+
return { line: value, truncated: false };
|
|
5136
|
+
}
|
|
5137
|
+
return {
|
|
5138
|
+
line: `${value.slice(0, MAX_DIFF_LINE_CHARS)}... [line truncated]`,
|
|
5139
|
+
truncated: true
|
|
5140
|
+
};
|
|
5141
|
+
}
|
|
5069
5142
|
function detectLineEnding(value) {
|
|
5070
5143
|
return value.includes("\r\n") ? "\r\n" : "\n";
|
|
5071
5144
|
}
|
|
@@ -5153,27 +5226,35 @@ function buildCompactDiff(oldContent, newContent) {
|
|
|
5153
5226
|
const oldContextEnd = Math.min(oldLines.length - 1, oldSuffix + 3);
|
|
5154
5227
|
const width = String(Math.max(oldLines.length, newLines.length)).length;
|
|
5155
5228
|
const output = [];
|
|
5229
|
+
let lineTruncated = false;
|
|
5230
|
+
const pushLine = (value) => {
|
|
5231
|
+
const bounded2 = truncateDiffLine(value);
|
|
5232
|
+
output.push(bounded2.line);
|
|
5233
|
+
lineTruncated ||= bounded2.truncated;
|
|
5234
|
+
};
|
|
5156
5235
|
if (contextStart > 0) {
|
|
5157
|
-
|
|
5236
|
+
pushLine(` ${"".padStart(width)} ...`);
|
|
5158
5237
|
}
|
|
5159
5238
|
for (let index = contextStart; index < prefix; index += 1) {
|
|
5160
|
-
|
|
5239
|
+
pushLine(` ${String(index + 1).padStart(width)} ${oldLines[index]}`);
|
|
5161
5240
|
}
|
|
5162
5241
|
for (let index = prefix; index <= oldSuffix; index += 1) {
|
|
5163
|
-
|
|
5242
|
+
pushLine(`-${String(index + 1).padStart(width)} ${oldLines[index]}`);
|
|
5164
5243
|
}
|
|
5165
5244
|
for (let index = prefix; index <= newSuffix; index += 1) {
|
|
5166
|
-
|
|
5245
|
+
pushLine(`+${String(index + 1).padStart(width)} ${newLines[index]}`);
|
|
5167
5246
|
}
|
|
5168
5247
|
for (let index = newSuffix + 1; index <= newContextEnd; index += 1) {
|
|
5169
|
-
|
|
5248
|
+
pushLine(` ${String(index + 1).padStart(width)} ${newLines[index]}`);
|
|
5170
5249
|
}
|
|
5171
5250
|
if (newContextEnd < newLines.length - 1 || oldContextEnd < oldLines.length - 1) {
|
|
5172
|
-
|
|
5251
|
+
pushLine(` ${"".padStart(width)} ...`);
|
|
5173
5252
|
}
|
|
5253
|
+
const bounded = truncateText(output.join("\n"), MAX_TEXT_CHARS);
|
|
5174
5254
|
return {
|
|
5175
|
-
diff:
|
|
5176
|
-
firstChangedLine: firstChangedLine(oldContent, newContent)
|
|
5255
|
+
diff: bounded.content,
|
|
5256
|
+
firstChangedLine: firstChangedLine(oldContent, newContent),
|
|
5257
|
+
truncated: lineTruncated || bounded.truncated
|
|
5177
5258
|
};
|
|
5178
5259
|
}
|
|
5179
5260
|
function validateAndApplyTextEdits(content, edits, targetName) {
|
|
@@ -5402,7 +5483,6 @@ async function editFile(params) {
|
|
|
5402
5483
|
status: "success",
|
|
5403
5484
|
target: params.path,
|
|
5404
5485
|
data: {
|
|
5405
|
-
diff: diff.diff,
|
|
5406
5486
|
first_changed_line: diff.firstChangedLine,
|
|
5407
5487
|
path: params.path,
|
|
5408
5488
|
replacements: params.edits.length
|
|
@@ -5410,7 +5490,8 @@ async function editFile(params) {
|
|
|
5410
5490
|
diff: diff.diff,
|
|
5411
5491
|
first_changed_line: diff.firstChangedLine,
|
|
5412
5492
|
path: params.path,
|
|
5413
|
-
replacements: params.edits.length
|
|
5493
|
+
replacements: params.edits.length,
|
|
5494
|
+
truncated: diff.truncated
|
|
5414
5495
|
});
|
|
5415
5496
|
}
|
|
5416
5497
|
var editReplacementSchema = z5.object({
|
|
@@ -14716,7 +14797,11 @@ function createResumeState(args) {
|
|
|
14716
14797
|
if (!args.durability.shouldYield?.()) {
|
|
14717
14798
|
return void 0;
|
|
14718
14799
|
}
|
|
14719
|
-
|
|
14800
|
+
const nextResumeMessages = this.getResumeSnapshot(currentMessages);
|
|
14801
|
+
if (!isContinuablePiBoundary(nextResumeMessages)) {
|
|
14802
|
+
return void 0;
|
|
14803
|
+
}
|
|
14804
|
+
resumeMessages = nextResumeMessages;
|
|
14720
14805
|
return new CooperativeTurnYieldError(
|
|
14721
14806
|
`Agent turn yielded at a safe boundary after ${currentDurationMs()}ms`
|
|
14722
14807
|
);
|
|
@@ -14815,16 +14900,24 @@ function createResumeState(args) {
|
|
|
14815
14900
|
}
|
|
14816
14901
|
|
|
14817
14902
|
// src/chat/services/context-compaction.ts
|
|
14818
|
-
import {
|
|
14819
|
-
estimateContextTokens,
|
|
14820
|
-
estimateTokens
|
|
14821
|
-
} from "@earendil-works/pi-agent-core";
|
|
14822
14903
|
var RETAINED_USER_MESSAGE_TOKENS = 2e4;
|
|
14823
14904
|
var MAX_SUMMARY_INPUT_CHARS = 8e4;
|
|
14824
14905
|
var MAX_VISIBLE_CONTEXT_CHARS = 2e4;
|
|
14825
14906
|
var MAX_SUMMARY_CHARS = 6e3;
|
|
14826
14907
|
var MAX_RENDERED_MESSAGE_CHARS = 4e3;
|
|
14827
14908
|
var OMITTED_OLDER_CONTEXT_NOTICE = "[older context omitted]";
|
|
14909
|
+
var ContextInputLimitExceededError = class extends Error {
|
|
14910
|
+
constructor(estimatedTokens, inputLimitTokens) {
|
|
14911
|
+
super(
|
|
14912
|
+
`Agent context is ${estimatedTokens} estimated input tokens, above the ${inputLimitTokens} token limit`
|
|
14913
|
+
);
|
|
14914
|
+
this.estimatedTokens = estimatedTokens;
|
|
14915
|
+
this.inputLimitTokens = inputLimitTokens;
|
|
14916
|
+
this.name = "ContextInputLimitExceededError";
|
|
14917
|
+
}
|
|
14918
|
+
estimatedTokens;
|
|
14919
|
+
inputLimitTokens;
|
|
14920
|
+
};
|
|
14828
14921
|
function textPart(value) {
|
|
14829
14922
|
if (value && typeof value === "object" && value.type === "text" && typeof value.text === "string") {
|
|
14830
14923
|
return value.text;
|
|
@@ -14985,13 +15078,10 @@ async function summarizeContext(args, deps) {
|
|
|
14985
15078
|
return summary.slice(0, MAX_SUMMARY_CHARS);
|
|
14986
15079
|
}
|
|
14987
15080
|
function estimateHistoryTokens(messages) {
|
|
14988
|
-
|
|
14989
|
-
|
|
14990
|
-
const structuralEstimate = stripped.reduce(
|
|
14991
|
-
(total, message) => total + estimateTokens(message),
|
|
15081
|
+
return messages.reduce(
|
|
15082
|
+
(total, message) => total + estimateTextTokens(JSON.stringify(message) ?? ""),
|
|
14992
15083
|
0
|
|
14993
15084
|
);
|
|
14994
|
-
return Math.max(usageEstimate, structuralEstimate);
|
|
14995
15085
|
}
|
|
14996
15086
|
function buildReplacementProvenance(args) {
|
|
14997
15087
|
return [
|
|
@@ -15015,11 +15105,11 @@ async function maybeCompactWithDeps(args, deps) {
|
|
|
15015
15105
|
if ("reason" in source) {
|
|
15016
15106
|
return { compacted: false, reason: source.reason };
|
|
15017
15107
|
}
|
|
15018
|
-
const triggerTokens = deps.autoCompactionTriggerTokens ?? getAgentContextCompactionTriggerTokens();
|
|
15108
|
+
const triggerTokens = deps.autoCompactionTriggerTokens ?? getAgentContextCompactionTriggerTokens(args.modelId);
|
|
15019
15109
|
if (source.estimatedTokens <= triggerTokens) {
|
|
15020
15110
|
return { compacted: false, reason: "below_threshold" };
|
|
15021
15111
|
}
|
|
15022
|
-
args.onCompactionStart?.();
|
|
15112
|
+
await args.onCompactionStart?.();
|
|
15023
15113
|
let summary;
|
|
15024
15114
|
try {
|
|
15025
15115
|
summary = await summarizeContext(
|
|
@@ -15050,7 +15140,8 @@ async function maybeCompactWithDeps(args, deps) {
|
|
|
15050
15140
|
}
|
|
15051
15141
|
return await writeCompactedThreadContext(args, source.messages, summary, {
|
|
15052
15142
|
estimatedTokens: source.estimatedTokens,
|
|
15053
|
-
triggerTokens
|
|
15143
|
+
triggerTokens,
|
|
15144
|
+
inputLimitTokens: getAgentContextInputLimitTokens(args.modelId)
|
|
15054
15145
|
});
|
|
15055
15146
|
}
|
|
15056
15147
|
async function writeCompactedThreadContext(args, sourceMessages, summary, context) {
|
|
@@ -15066,6 +15157,7 @@ async function writeCompactedThreadContext(args, sourceMessages, summary, contex
|
|
|
15066
15157
|
userMessage(`${COMPACTION_SUMMARY_PREFIX}
|
|
15067
15158
|
${summary}`)
|
|
15068
15159
|
];
|
|
15160
|
+
const replacementInputTokens = estimateHistoryTokens(replacement);
|
|
15069
15161
|
const replacementProvenance = buildReplacementProvenance({
|
|
15070
15162
|
retained,
|
|
15071
15163
|
sourceProvenance: sourceProjection.provenance
|
|
@@ -15076,6 +15168,16 @@ ${summary}`)
|
|
|
15076
15168
|
type: "compaction",
|
|
15077
15169
|
modelProfile: sourceProjection.modelProfile,
|
|
15078
15170
|
modelId: modelIdForProfile(botConfig, sourceProjection.modelProfile),
|
|
15171
|
+
details: {
|
|
15172
|
+
reason: "capacity",
|
|
15173
|
+
estimatedInputTokens: context.estimatedTokens,
|
|
15174
|
+
replacementInputTokens,
|
|
15175
|
+
triggerTokens: context.triggerTokens ?? getAgentContextCompactionTriggerTokens(args.modelId),
|
|
15176
|
+
inputLimitTokens: context.inputLimitTokens,
|
|
15177
|
+
inputMessageCount: sourceMessages.length,
|
|
15178
|
+
retainedMessageCount: replacement.length - 1,
|
|
15179
|
+
summaryChars: summary.length
|
|
15180
|
+
},
|
|
15079
15181
|
replacementHistory: replacement.map((message, index) => {
|
|
15080
15182
|
const sourceEventSeq = index < retained.length ? sourceProjection.seqs[retained[index].sourceIndex] : void 0;
|
|
15081
15183
|
return {
|
|
@@ -15137,6 +15239,114 @@ ${await summarizeContext(args, deps)}`;
|
|
|
15137
15239
|
});
|
|
15138
15240
|
return messages;
|
|
15139
15241
|
}
|
|
15242
|
+
async function compactActiveContextIfNeeded(args, deps) {
|
|
15243
|
+
const pendingMessages = args.pendingMessages ?? [];
|
|
15244
|
+
const source = loadCompactionSource([
|
|
15245
|
+
...args.piMessages,
|
|
15246
|
+
...pendingMessages.map((entry) => entry.message)
|
|
15247
|
+
]);
|
|
15248
|
+
if ("reason" in source) {
|
|
15249
|
+
return { compacted: false, reason: source.reason };
|
|
15250
|
+
}
|
|
15251
|
+
const triggerTokens = getAgentContextCompactionTriggerTokens(args.modelId);
|
|
15252
|
+
if (source.estimatedTokens <= triggerTokens) {
|
|
15253
|
+
return { compacted: false, reason: "below_threshold" };
|
|
15254
|
+
}
|
|
15255
|
+
await args.onCompactionStart?.();
|
|
15256
|
+
const inputLimitTokens = getAgentContextInputLimitTokens(args.modelId);
|
|
15257
|
+
let summary;
|
|
15258
|
+
try {
|
|
15259
|
+
summary = await summarizeContext(
|
|
15260
|
+
{
|
|
15261
|
+
...args,
|
|
15262
|
+
piMessages: args.piMessages
|
|
15263
|
+
},
|
|
15264
|
+
deps
|
|
15265
|
+
);
|
|
15266
|
+
} catch (error) {
|
|
15267
|
+
if (source.estimatedTokens >= inputLimitTokens) {
|
|
15268
|
+
throw new ContextInputLimitExceededError(
|
|
15269
|
+
source.estimatedTokens,
|
|
15270
|
+
inputLimitTokens
|
|
15271
|
+
);
|
|
15272
|
+
}
|
|
15273
|
+
logWarn(
|
|
15274
|
+
"active_context_compaction_summary_failed",
|
|
15275
|
+
{
|
|
15276
|
+
messageConversationId: args.metadata?.threadId,
|
|
15277
|
+
userId: args.metadata?.actorId,
|
|
15278
|
+
destinationName: args.metadata?.channelId,
|
|
15279
|
+
runId: args.metadata?.runId,
|
|
15280
|
+
assistantUserName: botConfig.userName,
|
|
15281
|
+
modelId: args.modelId
|
|
15282
|
+
},
|
|
15283
|
+
{
|
|
15284
|
+
"app.context_input_limit_tokens": inputLimitTokens,
|
|
15285
|
+
"app.context_tokens_estimated": source.estimatedTokens,
|
|
15286
|
+
"exception.message": error instanceof Error ? error.message : String(error)
|
|
15287
|
+
},
|
|
15288
|
+
"Active context compaction failed below the hard input limit"
|
|
15289
|
+
);
|
|
15290
|
+
return { compacted: false, reason: "summary_failed" };
|
|
15291
|
+
}
|
|
15292
|
+
const summaryText = `${COMPACTION_SUMMARY_PREFIX}
|
|
15293
|
+
${summary}`;
|
|
15294
|
+
const runtimeMessage = retainRuntimeTurnContext(args.piMessages).at(-1);
|
|
15295
|
+
const summaryMessages = runtimeMessage ? [
|
|
15296
|
+
{
|
|
15297
|
+
...runtimeMessage,
|
|
15298
|
+
content: [
|
|
15299
|
+
...runtimeMessage.content,
|
|
15300
|
+
{ type: "text", text: renderCurrentInstruction(summaryText) }
|
|
15301
|
+
]
|
|
15302
|
+
}
|
|
15303
|
+
] : [userMessage(renderCurrentInstruction(summaryText))];
|
|
15304
|
+
const messages = [
|
|
15305
|
+
...summaryMessages,
|
|
15306
|
+
...pendingMessages.map((entry) => entry.message)
|
|
15307
|
+
];
|
|
15308
|
+
const replacementInputTokens = estimateHistoryTokens(messages);
|
|
15309
|
+
if (replacementInputTokens >= inputLimitTokens) {
|
|
15310
|
+
throw new ContextInputLimitExceededError(
|
|
15311
|
+
replacementInputTokens,
|
|
15312
|
+
inputLimitTokens
|
|
15313
|
+
);
|
|
15314
|
+
}
|
|
15315
|
+
const replacementMessages = stripRuntimeTurnContext(messages);
|
|
15316
|
+
args.signal?.throwIfAborted();
|
|
15317
|
+
await getConversationEventStore().replaceHistory(args.conversationId, {
|
|
15318
|
+
createdAtMs: Date.now(),
|
|
15319
|
+
data: {
|
|
15320
|
+
type: "compaction",
|
|
15321
|
+
modelProfile: args.modelProfile,
|
|
15322
|
+
modelId: args.modelId,
|
|
15323
|
+
details: {
|
|
15324
|
+
reason: "capacity",
|
|
15325
|
+
estimatedInputTokens: source.estimatedTokens,
|
|
15326
|
+
replacementInputTokens,
|
|
15327
|
+
triggerTokens,
|
|
15328
|
+
inputLimitTokens,
|
|
15329
|
+
inputMessageCount: source.messages.length,
|
|
15330
|
+
retainedMessageCount: pendingMessages.length,
|
|
15331
|
+
summaryChars: summary.length
|
|
15332
|
+
},
|
|
15333
|
+
replacementHistory: replacementMessages.map((message, index) => ({
|
|
15334
|
+
message,
|
|
15335
|
+
provenance: index === 0 ? contextProvenance : pendingMessages[index - 1]?.provenance ?? contextProvenance
|
|
15336
|
+
}))
|
|
15337
|
+
}
|
|
15338
|
+
});
|
|
15339
|
+
setSpanAttributes({
|
|
15340
|
+
"app.compaction.input_messages": source.messages.length,
|
|
15341
|
+
"app.compaction.replacement_tokens": replacementInputTokens,
|
|
15342
|
+
"app.compaction.retained_messages": pendingMessages.length,
|
|
15343
|
+
"app.compaction.summary_chars": summary.length,
|
|
15344
|
+
"app.compaction.trigger_tokens": triggerTokens,
|
|
15345
|
+
"app.context_input_limit_tokens": inputLimitTokens,
|
|
15346
|
+
"app.context_tokens_estimated": source.estimatedTokens
|
|
15347
|
+
});
|
|
15348
|
+
return { compacted: true, piMessages: messages };
|
|
15349
|
+
}
|
|
15140
15350
|
|
|
15141
15351
|
// src/chat/agent/index.ts
|
|
15142
15352
|
var AGENT_ABORT_SETTLE_GRACE_MS = 5e3;
|
|
@@ -15235,7 +15445,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
15235
15445
|
let mcpToolManager;
|
|
15236
15446
|
let connectedMcpProviders = /* @__PURE__ */ new Set();
|
|
15237
15447
|
let turnUsage;
|
|
15238
|
-
let
|
|
15448
|
+
let priorPhaseUsage;
|
|
15239
15449
|
const configuredReasoningLevel = policy.reasoningLevel ?? botConfig.reasoningLevel;
|
|
15240
15450
|
let turnRoute = configuredReasoningLevel ? configuredTurnRoute(
|
|
15241
15451
|
STANDARD_MODEL_PROFILE,
|
|
@@ -15286,6 +15496,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
15286
15496
|
const projection = await openConversationProjection({ conversationId });
|
|
15287
15497
|
activeModelProfile = projection.modelProfile;
|
|
15288
15498
|
activeModelId = modelIdForProfile(botConfig, activeModelProfile);
|
|
15499
|
+
let durableModelProfile = projection.modelProfile;
|
|
15289
15500
|
const shouldTrace = shouldEmitDevAgentTrace();
|
|
15290
15501
|
const spanContext = { modelId: activeModelId };
|
|
15291
15502
|
const availableSkills = await discoverRunSkills({
|
|
@@ -15390,7 +15601,30 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
15390
15601
|
});
|
|
15391
15602
|
const { routerBlocks, userContentParts } = buildPromptInput(input);
|
|
15392
15603
|
const preAgentPromptMessages = () => existingSessionRecord?.piMessages ?? [...input.piMessages ?? []];
|
|
15393
|
-
|
|
15604
|
+
const storedTurnRoute = await loadTurnRoute({ conversationId, turnId });
|
|
15605
|
+
if (storedTurnRoute) {
|
|
15606
|
+
const resumedAfterHandoff = activeModelProfile !== STANDARD_MODEL_PROFILE && activeModelProfile !== storedTurnRoute.modelProfile;
|
|
15607
|
+
if (resumedAfterHandoff) {
|
|
15608
|
+
const activeProfileConfig = profileConfig(
|
|
15609
|
+
botConfig,
|
|
15610
|
+
activeModelProfile
|
|
15611
|
+
);
|
|
15612
|
+
const resumedReasoningLevel = existingSessionRecord?.reasoningLevel ? parseTurnReasoningLevel(existingSessionRecord.reasoningLevel) : void 0;
|
|
15613
|
+
turnRoute = {
|
|
15614
|
+
profile: activeModelProfile,
|
|
15615
|
+
reasoningLevel: activeProfileConfig.reasoningLevel ?? resumedReasoningLevel ?? storedTurnRoute.reasoningLevel,
|
|
15616
|
+
reason: `resumed_handoff:${storedTurnRoute.modelProfile}:${activeModelProfile}`
|
|
15617
|
+
};
|
|
15618
|
+
} else {
|
|
15619
|
+
turnRoute = {
|
|
15620
|
+
profile: storedTurnRoute.modelProfile,
|
|
15621
|
+
reasoningLevel: storedTurnRoute.reasoningLevel,
|
|
15622
|
+
...storedTurnRoute.confidence !== void 0 ? { confidence: storedTurnRoute.confidence } : {},
|
|
15623
|
+
reason: `persisted:${storedTurnRoute.source}`,
|
|
15624
|
+
source: storedTurnRoute.source
|
|
15625
|
+
};
|
|
15626
|
+
}
|
|
15627
|
+
} else if (activeModelProfile === STANDARD_MODEL_PROFILE) {
|
|
15394
15628
|
turnRoute = await selectTurnRoute({
|
|
15395
15629
|
completeObject,
|
|
15396
15630
|
conversationContext: input.conversationContext,
|
|
@@ -15405,7 +15639,11 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
15405
15639
|
messageText: userInput,
|
|
15406
15640
|
profiles: botConfig.profiles
|
|
15407
15641
|
});
|
|
15408
|
-
|
|
15642
|
+
const routedProfileReasoningLevel = profileConfig(
|
|
15643
|
+
botConfig,
|
|
15644
|
+
turnRoute.profile
|
|
15645
|
+
).reasoningLevel;
|
|
15646
|
+
if (configuredReasoningLevel && !routedProfileReasoningLevel) {
|
|
15409
15647
|
turnRoute = {
|
|
15410
15648
|
...turnRoute,
|
|
15411
15649
|
reasoningLevel: configuredReasoningLevel,
|
|
@@ -15414,12 +15652,29 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
15414
15652
|
}
|
|
15415
15653
|
} else {
|
|
15416
15654
|
const activeProfileConfig = profileConfig(botConfig, activeModelProfile);
|
|
15417
|
-
|
|
15418
|
-
|
|
15419
|
-
|
|
15420
|
-
activeProfileConfig.reasoningLevel
|
|
15421
|
-
|
|
15655
|
+
const reasoningSource = activeProfileConfig.reasoningLevel ? "profile" : policy.reasoningLevel ? "agent_config" : "default";
|
|
15656
|
+
turnRoute = {
|
|
15657
|
+
profile: activeModelProfile,
|
|
15658
|
+
reasoningLevel: activeProfileConfig.reasoningLevel ?? policy.reasoningLevel ?? botConfig.reasoningLevel ?? "medium",
|
|
15659
|
+
reason: `inherited:${reasoningSource}`,
|
|
15660
|
+
source: "inherited"
|
|
15661
|
+
};
|
|
15422
15662
|
}
|
|
15663
|
+
const routedModelProfile = turnRoute.profile;
|
|
15664
|
+
const routedModelId = modelIdForProfile(botConfig, routedModelProfile);
|
|
15665
|
+
if (!storedTurnRoute) {
|
|
15666
|
+
await recordTurnRoute({
|
|
15667
|
+
conversationId,
|
|
15668
|
+
turnId,
|
|
15669
|
+
modelProfile: routedModelProfile,
|
|
15670
|
+
modelId: routedModelId,
|
|
15671
|
+
reasoningLevel: turnRoute.reasoningLevel,
|
|
15672
|
+
...turnRoute.confidence !== void 0 ? { confidence: turnRoute.confidence } : {},
|
|
15673
|
+
source: turnRoute.source ?? "configured"
|
|
15674
|
+
});
|
|
15675
|
+
}
|
|
15676
|
+
activeModelProfile = routedModelProfile;
|
|
15677
|
+
activeModelId = routedModelId;
|
|
15423
15678
|
const generatedFiles = [];
|
|
15424
15679
|
const artifactStatePatch = {};
|
|
15425
15680
|
const toolCalls = [];
|
|
@@ -15432,17 +15687,20 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
15432
15687
|
(profile) => profile !== STANDARD_MODEL_PROFILE && profile !== DEFAULT_HANDOFF_MODEL_PROFILE
|
|
15433
15688
|
).sort()
|
|
15434
15689
|
];
|
|
15690
|
+
const usageSinceCurrentBoundary = (messages) => {
|
|
15691
|
+
const usage = extractGenAiUsageSummary(
|
|
15692
|
+
...messages.slice(runResume.beforeMessageCount).filter(isAssistantMessage)
|
|
15693
|
+
);
|
|
15694
|
+
return hasAgentTurnUsage(usage) ? usage : void 0;
|
|
15695
|
+
};
|
|
15435
15696
|
const scheduleHandoff = async (args) => {
|
|
15436
|
-
if (args.profile ===
|
|
15697
|
+
if (args.profile === durableModelProfile) {
|
|
15437
15698
|
return;
|
|
15438
15699
|
}
|
|
15439
15700
|
const runtimeContext = retainRuntimeTurnContext(
|
|
15440
15701
|
args.runtimeContextSourceMessages ?? args.sourceMessages
|
|
15441
15702
|
);
|
|
15442
|
-
const
|
|
15443
|
-
...args.sourceMessages.slice(runResume.beforeMessageCount).filter(isAssistantMessage)
|
|
15444
|
-
);
|
|
15445
|
-
const phaseUsage = hasAgentTurnUsage(standardPhaseUsage) ? standardPhaseUsage : void 0;
|
|
15703
|
+
const phaseUsage = usageSinceCurrentBoundary(args.sourceMessages);
|
|
15446
15704
|
const selectedProfile = profileConfig(botConfig, args.profile);
|
|
15447
15705
|
const handoffReasoningLevel = selectedProfile.reasoningLevel ?? turnRoute.reasoningLevel;
|
|
15448
15706
|
const target = {
|
|
@@ -15480,8 +15738,11 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
15480
15738
|
runId
|
|
15481
15739
|
}
|
|
15482
15740
|
},
|
|
15483
|
-
{
|
|
15741
|
+
{
|
|
15742
|
+
completeText: (args2) => completeText(args2)
|
|
15743
|
+
}
|
|
15484
15744
|
);
|
|
15745
|
+
durableModelProfile = args.profile;
|
|
15485
15746
|
if (handoffReasoningLevel !== turnRoute.reasoningLevel) {
|
|
15486
15747
|
turnRoute = {
|
|
15487
15748
|
...turnRoute,
|
|
@@ -15489,7 +15750,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
15489
15750
|
reason: `profile_reasoning_override:${args.profile}:${turnRoute.reason}`
|
|
15490
15751
|
};
|
|
15491
15752
|
}
|
|
15492
|
-
|
|
15753
|
+
priorPhaseUsage = addAgentTurnUsage(priorPhaseUsage, phaseUsage);
|
|
15493
15754
|
pendingHandoff = {
|
|
15494
15755
|
messages: handoffMessages,
|
|
15495
15756
|
model: handoffModel,
|
|
@@ -15602,6 +15863,52 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
15602
15863
|
thinkingLevel
|
|
15603
15864
|
};
|
|
15604
15865
|
};
|
|
15866
|
+
const applyActiveContextCompaction = async (messages, hookSignal, pendingMessages, clearSteeringQueueOnCommit = false) => {
|
|
15867
|
+
const compaction = await compactActiveContextIfNeeded(
|
|
15868
|
+
{
|
|
15869
|
+
conversationContext: input.conversationContext,
|
|
15870
|
+
conversationId,
|
|
15871
|
+
metadata: {
|
|
15872
|
+
threadId: conversationId,
|
|
15873
|
+
channelId: slackDestination?.channelId,
|
|
15874
|
+
actorId: slackActor?.userId,
|
|
15875
|
+
runId
|
|
15876
|
+
},
|
|
15877
|
+
modelId: activeModelId,
|
|
15878
|
+
modelProfile: activeModelProfile,
|
|
15879
|
+
onCompactionStart: () => observers.onStatus?.({ text: "Compacting context" }),
|
|
15880
|
+
pendingMessages,
|
|
15881
|
+
piMessages: messages,
|
|
15882
|
+
signal: hookSignal
|
|
15883
|
+
},
|
|
15884
|
+
{
|
|
15885
|
+
completeText: (args) => completeText(args)
|
|
15886
|
+
}
|
|
15887
|
+
);
|
|
15888
|
+
if (!compaction.compacted || !compaction.piMessages) {
|
|
15889
|
+
return void 0;
|
|
15890
|
+
}
|
|
15891
|
+
priorPhaseUsage = addAgentTurnUsage(
|
|
15892
|
+
priorPhaseUsage,
|
|
15893
|
+
usageSinceCurrentBoundary(messages)
|
|
15894
|
+
);
|
|
15895
|
+
const replacement = [...compaction.piMessages];
|
|
15896
|
+
await runResume.requireDurableInputCheckpoint(replacement);
|
|
15897
|
+
agent.state.messages = replacement;
|
|
15898
|
+
runResume.setBeforeMessageCount(replacement.length);
|
|
15899
|
+
runResume.setTurnStartMessageIndex(0);
|
|
15900
|
+
runResume.adoptCommittedBoundary(replacement);
|
|
15901
|
+
if (clearSteeringQueueOnCommit && pendingMessages?.length) {
|
|
15902
|
+
agent.clearSteeringQueue();
|
|
15903
|
+
}
|
|
15904
|
+
return {
|
|
15905
|
+
context: {
|
|
15906
|
+
systemPrompt: baseInstructions,
|
|
15907
|
+
messages: replacement,
|
|
15908
|
+
tools: agent.state.tools
|
|
15909
|
+
}
|
|
15910
|
+
};
|
|
15911
|
+
};
|
|
15605
15912
|
let assistantMessageDeliveryError;
|
|
15606
15913
|
const deliverAssistantMessage = async (message) => {
|
|
15607
15914
|
const text = getAssistantMessageText(message);
|
|
@@ -15619,8 +15926,9 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
15619
15926
|
};
|
|
15620
15927
|
const drainSteeringMessages = async () => {
|
|
15621
15928
|
if (!durability.drainSteeringMessages) {
|
|
15622
|
-
return;
|
|
15929
|
+
return [];
|
|
15623
15930
|
}
|
|
15931
|
+
const acceptedMessages = [];
|
|
15624
15932
|
try {
|
|
15625
15933
|
let steeredMessageCount = 0;
|
|
15626
15934
|
await durability.drainSteeringMessages(async (messages) => {
|
|
@@ -15638,6 +15946,12 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
15638
15946
|
for (const message of piMessages) {
|
|
15639
15947
|
agent.steer(message);
|
|
15640
15948
|
}
|
|
15949
|
+
acceptedMessages.push(
|
|
15950
|
+
...piMessages.map((message, index) => ({
|
|
15951
|
+
message,
|
|
15952
|
+
provenance: messages[index].provenance
|
|
15953
|
+
}))
|
|
15954
|
+
);
|
|
15641
15955
|
steeredMessageCount += piMessages.length;
|
|
15642
15956
|
});
|
|
15643
15957
|
if (steeredMessageCount > 0) {
|
|
@@ -15663,6 +15977,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
15663
15977
|
"Agent turn steering message drain failed"
|
|
15664
15978
|
);
|
|
15665
15979
|
}
|
|
15980
|
+
return acceptedMessages;
|
|
15666
15981
|
};
|
|
15667
15982
|
const apiKeyOverride = getPiGatewayApiKey();
|
|
15668
15983
|
let pendingPiHookError;
|
|
@@ -15686,15 +16001,27 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
15686
16001
|
return void 0;
|
|
15687
16002
|
},
|
|
15688
16003
|
afterToolCall: async ({ result: result2 }, signal2) => runResume.timedOut && signal2?.aborted ? annotateTurnDeadlineToolResult(result2) : void 0,
|
|
15689
|
-
|
|
15690
|
-
|
|
15691
|
-
|
|
15692
|
-
|
|
15693
|
-
|
|
15694
|
-
|
|
15695
|
-
|
|
16004
|
+
prepareNextTurnWithContext: async (nextTurn, hookSignal) => {
|
|
16005
|
+
try {
|
|
16006
|
+
const handoffUpdate = applyPendingHandoff();
|
|
16007
|
+
const pendingMessages = await drainSteeringMessages();
|
|
16008
|
+
const capacityUpdate = await applyActiveContextCompaction(
|
|
16009
|
+
handoffUpdate ? currentAgentMessages() : nextTurn.context.messages,
|
|
16010
|
+
hookSignal,
|
|
16011
|
+
pendingMessages,
|
|
16012
|
+
true
|
|
16013
|
+
);
|
|
16014
|
+
const yieldError = runResume.prepareYieldIfDue(
|
|
16015
|
+
currentAgentMessages()
|
|
16016
|
+
);
|
|
16017
|
+
if (yieldError) {
|
|
16018
|
+
throw yieldError;
|
|
16019
|
+
}
|
|
16020
|
+
return capacityUpdate && handoffUpdate ? { ...handoffUpdate, ...capacityUpdate } : capacityUpdate ?? handoffUpdate;
|
|
16021
|
+
} catch (error) {
|
|
16022
|
+
pendingPiHookError = error instanceof Error ? error : new Error(String(error));
|
|
16023
|
+
throw error;
|
|
15696
16024
|
}
|
|
15697
|
-
return update;
|
|
15698
16025
|
},
|
|
15699
16026
|
initialState: {
|
|
15700
16027
|
systemPrompt: baseInstructions,
|
|
@@ -15859,6 +16186,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
15859
16186
|
};
|
|
15860
16187
|
const requestedProfile = activeModelProfile === STANDARD_MODEL_PROFILE ? turnRoute.profile : void 0;
|
|
15861
16188
|
let run;
|
|
16189
|
+
let handoffApplied = false;
|
|
15862
16190
|
if (requestedProfile && requestedProfile !== STANDARD_MODEL_PROFILE) {
|
|
15863
16191
|
const handoffAbortController = new AbortController();
|
|
15864
16192
|
await runAgentStep(
|
|
@@ -15870,19 +16198,29 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
15870
16198
|
}),
|
|
15871
16199
|
() => handoffAbortController.abort()
|
|
15872
16200
|
);
|
|
15873
|
-
applyPendingHandoff();
|
|
15874
|
-
if (shouldPromptAgent) {
|
|
15875
|
-
await runResume.requireDurableInputCheckpoint([
|
|
15876
|
-
...agent.state.messages,
|
|
15877
|
-
freshPromptMessage
|
|
15878
|
-
]);
|
|
15879
|
-
run = agent.prompt(freshPromptMessage);
|
|
15880
|
-
} else {
|
|
15881
|
-
run = agent.continue();
|
|
15882
|
-
}
|
|
15883
|
-
} else {
|
|
15884
|
-
run = shouldPromptAgent ? agent.prompt(freshPromptMessage) : agent.continue();
|
|
16201
|
+
handoffApplied = Boolean(applyPendingHandoff());
|
|
15885
16202
|
}
|
|
16203
|
+
const compactionAbortController = new AbortController();
|
|
16204
|
+
const capacityUpdate = await runAgentStep(
|
|
16205
|
+
applyActiveContextCompaction(
|
|
16206
|
+
[...agent.state.messages],
|
|
16207
|
+
compactionAbortController.signal,
|
|
16208
|
+
shouldPromptAgent ? [
|
|
16209
|
+
{
|
|
16210
|
+
message: freshPromptMessage,
|
|
16211
|
+
provenance: instructionProvenanceFor(actor)
|
|
16212
|
+
}
|
|
16213
|
+
] : void 0
|
|
16214
|
+
),
|
|
16215
|
+
() => compactionAbortController.abort()
|
|
16216
|
+
);
|
|
16217
|
+
if (shouldPromptAgent && handoffApplied && !capacityUpdate) {
|
|
16218
|
+
await runResume.requireDurableInputCheckpoint([
|
|
16219
|
+
...agent.state.messages,
|
|
16220
|
+
freshPromptMessage
|
|
16221
|
+
]);
|
|
16222
|
+
}
|
|
16223
|
+
run = shouldPromptAgent && !capacityUpdate ? agent.prompt(freshPromptMessage) : agent.continue();
|
|
15886
16224
|
let retryUsage;
|
|
15887
16225
|
try {
|
|
15888
16226
|
for (let attempt = 0; ; attempt += 1) {
|
|
@@ -15905,10 +16243,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
15905
16243
|
retryUsage,
|
|
15906
16244
|
currentUsage
|
|
15907
16245
|
);
|
|
15908
|
-
turnUsage = addAgentTurnUsage(
|
|
15909
|
-
handoffPhaseUsage,
|
|
15910
|
-
currentPhaseUsage
|
|
15911
|
-
);
|
|
16246
|
+
turnUsage = addAgentTurnUsage(priorPhaseUsage, currentPhaseUsage);
|
|
15912
16247
|
setSpanAttributes({
|
|
15913
16248
|
...outputMessagesAttribute ? { "gen_ai.output.messages": outputMessagesAttribute } : {},
|
|
15914
16249
|
...toGenAiMessagesTraceAttributes(
|
|
@@ -15931,8 +16266,8 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
15931
16266
|
}
|
|
15932
16267
|
const providerRetry = nextProviderRetry({
|
|
15933
16268
|
attempt,
|
|
15934
|
-
|
|
15935
|
-
|
|
16269
|
+
failure: lastAssistant,
|
|
16270
|
+
messages: agent.state.messages
|
|
15936
16271
|
});
|
|
15937
16272
|
if (!providerRetry) {
|
|
15938
16273
|
break;
|