@opengeni/worker-bundle 1.0.0-canary.1 → 1.0.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/activities/agent-run-admission.d.ts +3 -1
- package/dist/activities/agent-turn/admission.d.ts +24 -3
- package/dist/activities/agent-turn/agent-build.d.ts +4 -0
- package/dist/activities/agent-turn/claude-usage-observer.d.ts +58 -0
- package/dist/activities/agent-turn/code-search.d.ts +60 -0
- package/dist/activities/agent-turn/codex-capacity.d.ts +13 -0
- package/dist/activities/agent-turn/codex-plan-entitlement.d.ts +105 -0
- package/dist/activities/agent-turn/codex.d.ts +3 -2
- package/dist/activities/agent-turn/compaction-prep.d.ts +21 -5
- package/dist/activities/agent-turn/credential-leases.d.ts +19 -33
- package/dist/activities/agent-turn/credential-restriction.d.ts +3 -0
- package/dist/activities/agent-turn/errors.d.ts +82 -11
- package/dist/activities/agent-turn/failure-settlement.d.ts +6 -3
- package/dist/activities/agent-turn/final-reply.d.ts +18 -0
- package/dist/activities/agent-turn/finalization-monitor.d.ts +17 -0
- package/dist/activities/agent-turn/finalization.d.ts +4 -2
- package/dist/activities/agent-turn/github-repository-bindings.d.ts +2 -0
- package/dist/activities/agent-turn/governance-model.d.ts +9 -2
- package/dist/activities/agent-turn/history-sink.d.ts +2 -0
- package/dist/activities/agent-turn/history.d.ts +2 -0
- package/dist/activities/agent-turn/input-wait-reply.d.ts +41 -0
- package/dist/activities/agent-turn/media-artifacts.d.ts +5 -3
- package/dist/activities/agent-turn/model-call-admission.d.ts +15 -0
- package/dist/activities/agent-turn/model-usage.d.ts +6 -0
- package/dist/activities/agent-turn/model-wire-dispatch.d.ts +15 -0
- package/dist/activities/agent-turn/optional-repositories.d.ts +59 -0
- package/dist/activities/agent-turn/provider-dispatch-barrier.d.ts +12 -1
- package/dist/activities/agent-turn/quiescence.d.ts +7 -7
- package/dist/activities/agent-turn/recovery-warning.d.ts +9 -0
- package/dist/activities/agent-turn/refresh-credentials.d.ts +6 -0
- package/dist/activities/agent-turn/run-credentials.d.ts +8 -3
- package/dist/activities/agent-turn/sandbox-establish.d.ts +2 -1
- package/dist/activities/agent-turn/sandbox-provision.d.ts +3 -1
- package/dist/activities/agent-turn/sandbox-route.d.ts +3 -20
- package/dist/activities/agent-turn/sandbox-runtime.d.ts +2 -2
- package/dist/activities/agent-turn/session-title.d.ts +34 -2
- package/dist/activities/agent-turn/skill-checkout.d.ts +25 -6
- package/dist/activities/agent-turn/skill-read.d.ts +70 -2
- package/dist/activities/agent-turn/skill-remove.d.ts +14 -0
- package/dist/activities/agent-turn/skill-search.d.ts +3 -1
- package/dist/activities/agent-turn/skill-tools.d.ts +15 -2
- package/dist/activities/agent-turn/skill-transfer.d.ts +18 -6
- package/dist/activities/agent-turn/stream-attempt.d.ts +7 -3
- package/dist/activities/agent-turn/subscription-lease.d.ts +38 -0
- package/dist/activities/agent-turn/tool-environment.d.ts +56 -6
- package/dist/activities/agent-turn/tool-policy.d.ts +43 -0
- package/dist/activities/agent-turn/turn-context.d.ts +29 -0
- package/dist/activities/agent-turn/turn-sandbox-access.d.ts +3 -0
- package/dist/activities/agent-turn/xai-capacity.d.ts +2 -1
- package/dist/activities/automations.d.ts +3 -1
- package/dist/activities/browser-deadline-checkpoint.d.ts +29 -0
- package/dist/activities/codemode-dispatcher.d.ts +9 -2
- package/dist/activities/codex-capacity.d.ts +18 -2
- package/dist/activities/codex-rotation.d.ts +7 -1
- package/dist/activities/context-compaction.d.ts +16 -2
- package/dist/activities/gmail-files.d.ts +32 -0
- package/dist/activities/goals.d.ts +8 -0
- package/dist/activities/knowledge-indexing.d.ts +19 -0
- package/dist/activities/mcp-account-routes.d.ts +3 -0
- package/dist/activities/mcp-credentials.d.ts +12 -13
- package/dist/activities/mcp-operation-authority.d.ts +0 -5
- package/dist/activities/model-call-fact-reconciler.d.ts +34 -0
- package/dist/activities/open-suffix-resume.d.ts +13 -0
- package/dist/activities/parent-wake.d.ts +6 -12
- package/dist/activities/retained-screenshots.d.ts +7 -2
- package/dist/activities/rig-verification.d.ts +2 -3
- package/dist/activities/run-credential-renewal.d.ts +1 -0
- package/dist/activities/run-credentials.d.ts +15 -3
- package/dist/activities/sandbox-images.d.ts +1 -1
- package/dist/activities/sandbox-lease.d.ts +47 -9
- package/dist/activities/scheduled-tasks.d.ts +4 -35
- package/dist/activities/session-state.d.ts +70 -3
- package/dist/activities/types.d.ts +55 -6
- package/dist/activities/workspace-capture.d.ts +2 -0
- package/dist/activities/workspace-credential-provider.d.ts +46 -0
- package/dist/{activities-control-HMFGSKC5.js → activities-control-BNPTRTOE.js} +1896 -418
- package/dist/activities-control-BNPTRTOE.js.map +1 -0
- package/dist/activities-control.d.ts +182 -4
- package/dist/{activities-turn-AP67JADS.js → activities-turn-5LGZOSVU.js} +4476 -1327
- package/dist/activities-turn-5LGZOSVU.js.map +1 -0
- package/dist/activities.d.ts +182 -4
- package/dist/artifact-materializer-entry.js +5 -2
- package/dist/artifact-materializer-entry.js.map +1 -1
- package/dist/artifact-outbox-entry.js +5 -2
- package/dist/artifact-outbox-entry.js.map +1 -1
- package/dist/browser-deadline-checkpoint-contract.d.ts +2 -0
- package/dist/{chunk-A4XQWVZK.js → chunk-3ZTRWDMN.js} +307 -4
- package/dist/chunk-3ZTRWDMN.js.map +1 -0
- package/dist/{chunk-RAMNYSAW.js → chunk-4ER3YXOT.js} +22 -4
- package/dist/chunk-4ER3YXOT.js.map +1 -0
- package/dist/{chunk-CYITU5UH.js → chunk-LJX7Z2KP.js} +1445 -343
- package/dist/chunk-LJX7Z2KP.js.map +1 -0
- package/dist/editable-artifact-materializer-service.d.ts +2 -2
- package/dist/editable-artifact-outbox-service.d.ts +2 -2
- package/dist/host-export-pump.d.ts +3 -1
- package/dist/host-export.d.ts +1 -1
- package/dist/host-export.js +1 -1
- package/dist/http.d.ts +1 -1
- package/dist/index.d.ts +95 -3
- package/dist/index.js +137 -43
- package/dist/index.js.map +1 -1
- package/dist/observability-metrics.d.ts +118 -8
- package/dist/retained-process-diagnostics.d.ts +4 -0
- package/dist/retained-process-retry.d.ts +7 -0
- package/dist/sandbox-resume.d.ts +55 -13
- package/dist/sandbox-routing.d.ts +5 -3
- package/dist/sandbox-snapshot-diagnostics.d.ts +20 -0
- package/dist/session-event-fanout.d.ts +6 -0
- package/dist/warm-capture-holder.d.ts +3 -0
- package/dist/worker-service-lifecycle.d.ts +12 -0
- package/dist/workflow-bundle.js +273 -41
- package/dist/workflows/activities.d.ts +1 -1
- package/dist/workflows/browser-deadline-checkpoint.d.ts +9 -0
- package/dist/workflows/scheduled-tasks.d.ts +4 -0
- package/dist/workflows/session.d.ts +36 -0
- package/dist/workflows.d.ts +1 -0
- package/package.json +21 -19
- package/src/activities/agent-run-admission.ts +17 -1
- package/src/activities/agent-turn/admission.ts +66 -3
- package/src/activities/agent-turn/agent-build.ts +84 -10
- package/src/activities/agent-turn/claim.ts +186 -43
- package/src/activities/agent-turn/claude-usage-observer.ts +221 -0
- package/src/activities/agent-turn/code-search.ts +275 -0
- package/src/activities/agent-turn/codex-capacity.ts +172 -8
- package/src/activities/agent-turn/codex-plan-entitlement.ts +254 -0
- package/src/activities/agent-turn/codex.ts +13 -5
- package/src/activities/agent-turn/compaction-prep.ts +170 -102
- package/src/activities/agent-turn/credential-leases.ts +122 -216
- package/src/activities/agent-turn/credential-restriction.ts +14 -0
- package/src/activities/agent-turn/errors.ts +647 -48
- package/src/activities/agent-turn/failure-settlement.ts +682 -130
- package/src/activities/agent-turn/final-reply.ts +46 -0
- package/src/activities/agent-turn/finalization-monitor.ts +120 -0
- package/src/activities/agent-turn/finalization.ts +146 -43
- package/src/activities/agent-turn/github-repository-bindings.ts +3 -1
- package/src/activities/agent-turn/governance-model.ts +69 -28
- package/src/activities/agent-turn/history-sink.ts +16 -2
- package/src/activities/agent-turn/history.ts +38 -11
- package/src/activities/agent-turn/input-wait-reply.ts +103 -0
- package/src/activities/agent-turn/knowledge-source-tools.ts +2 -0
- package/src/activities/agent-turn/media-artifacts.ts +2 -1
- package/src/activities/agent-turn/model-call-admission.ts +94 -0
- package/src/activities/agent-turn/model-usage.ts +64 -3
- package/src/activities/agent-turn/model-wire-dispatch.ts +27 -0
- package/src/activities/agent-turn/optional-repositories.ts +224 -0
- package/src/activities/agent-turn/provider-dispatch-barrier.ts +22 -0
- package/src/activities/agent-turn/quiescence.ts +10 -7
- package/src/activities/agent-turn/recovery-warning.ts +16 -0
- package/src/activities/agent-turn/refresh-credentials.ts +44 -0
- package/src/activities/agent-turn/run-credentials.ts +116 -55
- package/src/activities/agent-turn/run.ts +320 -93
- package/src/activities/agent-turn/sandbox-establish.ts +84 -8
- package/src/activities/agent-turn/sandbox-provision.ts +3 -1
- package/src/activities/agent-turn/sandbox-route.ts +4 -21
- package/src/activities/agent-turn/sandbox-runtime.ts +343 -18
- package/src/activities/agent-turn/session-title.ts +81 -5
- package/src/activities/agent-turn/skill-checkout.ts +111 -24
- package/src/activities/agent-turn/skill-install.ts +1 -1
- package/src/activities/agent-turn/skill-read.ts +374 -28
- package/src/activities/agent-turn/skill-remove.ts +46 -0
- package/src/activities/agent-turn/skill-save.ts +1 -1
- package/src/activities/agent-turn/skill-search.ts +10 -1
- package/src/activities/agent-turn/skill-selection.ts +4 -0
- package/src/activities/agent-turn/skill-tools.ts +112 -18
- package/src/activities/agent-turn/skill-transfer.ts +68 -23
- package/src/activities/agent-turn/stream-attempt.ts +313 -77
- package/src/activities/agent-turn/subscription-lease.ts +115 -0
- package/src/activities/agent-turn/tool-environment.ts +316 -167
- package/src/activities/agent-turn/tool-policy.ts +80 -1
- package/src/activities/agent-turn/turn-context.ts +35 -0
- package/src/activities/agent-turn/turn-sandbox-access.ts +7 -1
- package/src/activities/agent-turn/xai-capacity.ts +94 -51
- package/src/activities/automations.ts +76 -4
- package/src/activities/browser-deadline-checkpoint.ts +279 -0
- package/src/activities/capabilities.ts +108 -11
- package/src/activities/codemode-dispatcher.ts +36 -8
- package/src/activities/codex-capacity.ts +60 -25
- package/src/activities/codex-rotation.ts +39 -17
- package/src/activities/context-compaction.ts +75 -18
- package/src/activities/gmail-files.ts +88 -0
- package/src/activities/goals.ts +116 -121
- package/src/activities/google-drive-publication.ts +1 -3
- package/src/activities/image-generation-operation.ts +1 -1
- package/src/activities/knowledge-indexing.ts +269 -15
- package/src/activities/knowledge-source-sync.ts +10 -0
- package/src/activities/mcp-account-routes.ts +17 -0
- package/src/activities/mcp-credentials.ts +83 -194
- package/src/activities/mcp-operation-authority.ts +16 -41
- package/src/activities/model-call-fact-reconciler.ts +112 -0
- package/src/activities/open-suffix-resume.ts +15 -2
- package/src/activities/parent-wake.ts +46 -21
- package/src/activities/retained-screenshots.ts +82 -11
- package/src/activities/rig-verification.ts +38 -37
- package/src/activities/run-credential-renewal.ts +13 -1
- package/src/activities/run-credentials.ts +59 -17
- package/src/activities/run-input.ts +25 -16
- package/src/activities/sandbox-images.ts +0 -1
- package/src/activities/sandbox-lease.ts +798 -82
- package/src/activities/scheduled-tasks.ts +550 -178
- package/src/activities/session-state.ts +245 -6
- package/src/activities/site-auth-maintenance.ts +3 -0
- package/src/activities/types.ts +72 -5
- package/src/activities/workflow-wake.ts +2 -17
- package/src/activities/workspace-capture.ts +13 -2
- package/src/activities/workspace-credential-provider.ts +283 -0
- package/src/activities-control.ts +4 -0
- package/src/activities-turn.ts +5 -0
- package/src/activities.ts +13 -0
- package/src/activity-services.ts +16 -4
- package/src/browser-deadline-checkpoint-contract.ts +5 -0
- package/src/editable-artifact-hint-broker.ts +3 -0
- package/src/editable-artifact-materializer-service.ts +7 -3
- package/src/editable-artifact-outbox-service.ts +4 -4
- package/src/github-rest-mcp.ts +1 -2
- package/src/host-export-pump.ts +26 -4
- package/src/host-export.ts +3 -0
- package/src/http.ts +4 -2
- package/src/index.ts +99 -37
- package/src/observability-metrics.ts +510 -5
- package/src/personal-github-git-credentials.ts +2 -1
- package/src/pr-review-credentials.ts +1 -3
- package/src/retained-process-diagnostics.ts +50 -0
- package/src/retained-process-retry.ts +36 -0
- package/src/sandbox-resume.ts +388 -101
- package/src/sandbox-routing.ts +150 -25
- package/src/sandbox-snapshot-diagnostics.ts +112 -0
- package/src/session-event-fanout.ts +23 -0
- package/src/warm-capture-holder.ts +15 -0
- package/src/worker-service-lifecycle.ts +53 -0
- package/src/workflows/activities.ts +16 -1
- package/src/workflows/browser-deadline-checkpoint.ts +50 -0
- package/src/workflows/file-upload-reaper.ts +2 -0
- package/src/workflows/scheduled-tasks.ts +26 -13
- package/src/workflows/session.ts +242 -22
- package/src/workflows.ts +4 -0
- package/dist/activities/agent-turn/knowledge-sources.d.ts +0 -20
- package/dist/activities/packs.d.ts +0 -55
- package/dist/activities-control-HMFGSKC5.js.map +0 -1
- package/dist/activities-turn-AP67JADS.js.map +0 -1
- package/dist/chunk-A4XQWVZK.js.map +0 -1
- package/dist/chunk-CYITU5UH.js.map +0 -1
- package/dist/chunk-RAMNYSAW.js.map +0 -1
- package/src/activities/agent-turn/knowledge-sources.ts +0 -86
- package/src/activities/packs.ts +0 -166
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
import { measureMcpPhase, withMcpCallIdentity } from "@opengeni/observability";
|
|
1
2
|
import {
|
|
3
|
+
appendSessionHistoryItems,
|
|
4
|
+
sessionTurnFinalReplyFacts,
|
|
5
|
+
sessionTurnHasFinalReplyNudge,
|
|
2
6
|
getSessionEvent,
|
|
3
7
|
getHumanInputResumeForEvent,
|
|
4
8
|
getSessionHumanInputRequest,
|
|
@@ -15,13 +19,17 @@ import {
|
|
|
15
19
|
} from "@opengeni/db";
|
|
16
20
|
import { publishDurableSessionEvents } from "@opengeni/events";
|
|
17
21
|
import {
|
|
22
|
+
AssistantMessagePhaseTracker,
|
|
18
23
|
normalizeModelCallUsage,
|
|
19
24
|
normalizeSdkEvent,
|
|
25
|
+
withMcpToolDisplayMetadata,
|
|
26
|
+
withToolCallFamily,
|
|
20
27
|
extractOpenSuffixFromRunState,
|
|
21
28
|
assertOpenSuffixResumable,
|
|
22
29
|
interruptionKindForCallItem,
|
|
23
30
|
releaseMcpResultCustomDataFromSdkEvent,
|
|
24
31
|
findCompactionNeededError,
|
|
32
|
+
compactionProviderRejection,
|
|
25
33
|
withRunCredentialsSession,
|
|
26
34
|
runOwnedSandboxSetup,
|
|
27
35
|
type SandboxFileDownload,
|
|
@@ -59,7 +67,7 @@ import {
|
|
|
59
67
|
import {
|
|
60
68
|
compactRetainedScreenshotHistory,
|
|
61
69
|
sdkEventContainsInlineImage,
|
|
62
|
-
|
|
70
|
+
retainSessionScreenshot,
|
|
63
71
|
typedScreenshotFromSdkEvent,
|
|
64
72
|
unavailableRetainedSessionImage,
|
|
65
73
|
} from "../retained-screenshots";
|
|
@@ -69,6 +77,7 @@ import {
|
|
|
69
77
|
isCompletedGeneratedImageSdkEvent,
|
|
70
78
|
} from "../generated-images";
|
|
71
79
|
import { ToolResultSpill } from "./tool-result-spill";
|
|
80
|
+
import { ownedTurnSandboxForAgent } from "./turn-sandbox-access";
|
|
72
81
|
import { createTurnCredentialLeases } from "./credential-leases";
|
|
73
82
|
import { createTurnMediaArtifacts } from "./media-artifacts";
|
|
74
83
|
import { createTurnHistorySink } from "./history-sink";
|
|
@@ -79,23 +88,27 @@ import {
|
|
|
79
88
|
import {
|
|
80
89
|
OPEN_SUFFIX_RUN_STATE_BLOB,
|
|
81
90
|
resolveWorkspaceAgentHumanInputEnabled,
|
|
91
|
+
withPublicApprovalFields,
|
|
82
92
|
type RetainedArtifactMetadata,
|
|
83
93
|
type SessionEvent,
|
|
94
|
+
type SessionTurn,
|
|
84
95
|
} from "@opengeni/contracts";
|
|
85
96
|
import { createModelCheckpointMemoryCollector } from "../../model-checkpoint-memory-collector";
|
|
97
|
+
import { createModelCallAdmission } from "./model-call-admission";
|
|
86
98
|
|
|
87
99
|
import {
|
|
88
100
|
assertWorkspaceHumanInputAllowed,
|
|
89
101
|
stableHumanInputRequestId,
|
|
90
102
|
stableInteractionInterventionId,
|
|
91
103
|
stableInteractionInterventionOperationId,
|
|
92
|
-
|
|
93
|
-
ensureRunAllowed,
|
|
104
|
+
ensureRunAllowedBetweenModelCalls,
|
|
94
105
|
} from "./admission";
|
|
95
106
|
import {
|
|
96
107
|
compactionFailureReason,
|
|
97
108
|
safeErrorDiagnostic,
|
|
98
109
|
compactionFailureReasonFromError,
|
|
110
|
+
compactionFailureTurnEventPayload,
|
|
111
|
+
modelPreparationFailureEventPayload,
|
|
99
112
|
isCompactionSummaryFailure,
|
|
100
113
|
PostCompactionContinuationEmptyError,
|
|
101
114
|
shouldRecoverCompactionProviderFailure,
|
|
@@ -104,9 +117,9 @@ import {
|
|
|
104
117
|
import {
|
|
105
118
|
pendingToolCallFromSdkEvent,
|
|
106
119
|
toolCallProducesRetainableSessionImage,
|
|
120
|
+
retainableBrowserScreenshotToolCall,
|
|
107
121
|
completedToolCallFromSdkEvent,
|
|
108
122
|
} from "./history";
|
|
109
|
-
import { checkpointHistoryBeforeProviderDispatch } from "./provider-dispatch-barrier";
|
|
110
123
|
import {
|
|
111
124
|
modelUsageSourceKey,
|
|
112
125
|
recordCompletedModelCallBeforeOwnershipFences,
|
|
@@ -121,14 +134,19 @@ import {
|
|
|
121
134
|
recordModelUsageAndDebitCredits,
|
|
122
135
|
recordAuthoritativeModelCallFact,
|
|
123
136
|
} from "./model-usage";
|
|
124
|
-
import {
|
|
137
|
+
import {
|
|
138
|
+
sessionTitleGenerationOptions,
|
|
139
|
+
startParallelSessionTitleGeneration,
|
|
140
|
+
} from "./session-title";
|
|
125
141
|
import {
|
|
126
142
|
assertAgentStreamNotCancelled,
|
|
127
143
|
assertSuccessfulAgentStreamCompletion,
|
|
128
144
|
requireAgentStreamFinalOutput,
|
|
129
145
|
} from "./quiescence";
|
|
146
|
+
import { inputWaitReply, latestDurableTurnMessageText } from "./input-wait-reply";
|
|
130
147
|
import { waitForTurnOperation } from "./sandbox-provision";
|
|
131
148
|
import { createSharedRigSetupCoordinator } from "./sandbox-shared-preparation";
|
|
149
|
+
import { finalReplyNudge, needsFinalReply } from "./final-reply";
|
|
132
150
|
|
|
133
151
|
import type { CompactionSummarizer } from "../context-compaction";
|
|
134
152
|
import type { TurnExecutionPolicyV1 } from "@opengeni/contracts";
|
|
@@ -169,11 +187,12 @@ export type TurnStreamAttemptDeps = {
|
|
|
169
187
|
providerTurn: ProviderTurnState;
|
|
170
188
|
leases: ReturnType<typeof createTurnCredentialLeases>;
|
|
171
189
|
historySink: ReturnType<typeof createTurnHistorySink>;
|
|
190
|
+
checkpointBeforeProviderDispatch: () => Promise<void>;
|
|
172
191
|
media: ReturnType<typeof createTurnMediaArtifacts>;
|
|
173
192
|
toolResultSpill: ToolResultSpill;
|
|
174
193
|
claimedResult: ClaimedResult;
|
|
175
194
|
flushRuntimeBatcher: () => Promise<void>;
|
|
176
|
-
finalizeTurnOpStreamOps: () => Promise<void>;
|
|
195
|
+
finalizeTurnOpStreamOps: (toolCallIds?: readonly string[]) => Promise<void>;
|
|
177
196
|
runWorkspaceMutationForSandbox: <T>(
|
|
178
197
|
sandbox: ResumedTurnSandbox,
|
|
179
198
|
operation: string,
|
|
@@ -221,7 +240,13 @@ export type TurnStreamAttemptDeps = {
|
|
|
221
240
|
activeSandboxBackend: Settings["sandboxBackend"] | undefined;
|
|
222
241
|
groupBoxBackend: Settings["sandboxBackend"];
|
|
223
242
|
turnExecutionPolicy: TurnExecutionPolicyV1;
|
|
224
|
-
turn:
|
|
243
|
+
turn: Pick<SessionTurn, "initiator" | "initiatorContext"> & {
|
|
244
|
+
initiatingHumanSubjectId: string | null;
|
|
245
|
+
id: string;
|
|
246
|
+
executionGeneration: number;
|
|
247
|
+
model: string;
|
|
248
|
+
source?: string;
|
|
249
|
+
};
|
|
225
250
|
trigger: NonNullable<Awaited<ReturnType<typeof getSessionEvent>>>;
|
|
226
251
|
humanInputResume: Awaited<ReturnType<typeof getHumanInputResumeForEvent>>;
|
|
227
252
|
attachPendingUpdatesAfterOpenSuffix: () => Promise<boolean>;
|
|
@@ -287,6 +312,7 @@ export async function runTurnStreamAttempt(
|
|
|
287
312
|
providerTurn,
|
|
288
313
|
leases,
|
|
289
314
|
historySink,
|
|
315
|
+
checkpointBeforeProviderDispatch,
|
|
290
316
|
media,
|
|
291
317
|
toolResultSpill,
|
|
292
318
|
claimedResult,
|
|
@@ -560,15 +586,45 @@ export async function runTurnStreamAttempt(
|
|
|
560
586
|
// calling runStreamAttempt again; resetting this state there would reuse
|
|
561
587
|
// the first no-response-ID fallback key and suppress a real model call.
|
|
562
588
|
const modelResponseState = createModelResponseEventState(claimedModelUsageSourceKeys);
|
|
589
|
+
// Text of the newest assistant message any stream of this activity completed
|
|
590
|
+
// durably: the reply a wait-ended human turn records on turn.completed.
|
|
591
|
+
let latestAssistantMessageText: string | null = null;
|
|
563
592
|
let workerPreparationTotalRecorded = false;
|
|
593
|
+
let toolsExecuted = false;
|
|
594
|
+
let finalReplyNudged = false;
|
|
595
|
+
const revalidateModelCallAdmission = async () => {
|
|
596
|
+
await historySink.reconcileConversationTruth({ requireDurable: true });
|
|
597
|
+
await ensureRunAllowedBetweenModelCalls({
|
|
598
|
+
settings,
|
|
599
|
+
db,
|
|
600
|
+
accountId: input.accountId,
|
|
601
|
+
workspaceId: input.workspaceId,
|
|
602
|
+
isExternallyBilledTurn: billingState.isExternallyBilledTurn,
|
|
603
|
+
entitlements,
|
|
604
|
+
chargesOpenGeniCredits: billingState.chargesOpenGeniCredits,
|
|
605
|
+
countsTowardTokenCap: billingState.countsTowardTokenCap,
|
|
606
|
+
initiatingHumanSubjectId: turn.initiatingHumanSubjectId,
|
|
607
|
+
});
|
|
608
|
+
};
|
|
564
609
|
const runStreamAttempt = async (options: {
|
|
565
610
|
requireTerminalModelResponse: boolean;
|
|
566
|
-
}): Promise<RunAgentTurnResult> => {
|
|
611
|
+
}): Promise<RunAgentTurnResult | "reply_nudge"> => {
|
|
567
612
|
if (!runInput) {
|
|
568
613
|
throw new Error("Run input was not prepared");
|
|
569
614
|
}
|
|
570
|
-
|
|
615
|
+
// The previous stream was persisted before compaction; the sink is now
|
|
616
|
+
// seeded from its durable replacement. Do not reconcile the old prefix
|
|
617
|
+
// against that replacement while checking the next stream's admission.
|
|
571
618
|
eventing.stream = undefined;
|
|
619
|
+
// Compaction commits its paid usage and replacement history before this
|
|
620
|
+
// boundary, both during preparation and in-activity recovery. Revalidate
|
|
621
|
+
// the accepted turn's frozen human before another stream can dispatch.
|
|
622
|
+
if (options.requireTerminalModelResponse) await revalidateModelCallAdmission();
|
|
623
|
+
const modelCallAdmission = createModelCallAdmission({
|
|
624
|
+
signal: runtimeCancellationSignal,
|
|
625
|
+
admit: revalidateModelCallAdmission,
|
|
626
|
+
});
|
|
627
|
+
const responseCountBeforeStream = modelResponseState.responseCount;
|
|
572
628
|
eventing.batcher = null;
|
|
573
629
|
// The SDK emits every processed call item for one model response before
|
|
574
630
|
// it emits any result for that response. Keep that response-local batch
|
|
@@ -578,6 +634,12 @@ export async function runTurnStreamAttempt(
|
|
|
578
634
|
let currentToolBatchCallIds = new Set<string>();
|
|
579
635
|
let currentToolBatchCompletedCallIds = new Set<string>();
|
|
580
636
|
let streamSawPerResponseUsage = false;
|
|
637
|
+
// Deltas learn the phase a provider declares when it announces a message;
|
|
638
|
+
// undeclared messages the SDK runs past (same response asks for tools)
|
|
639
|
+
// are commentary. Every SDK event of this stream is normalized once.
|
|
640
|
+
const messagePhases = new AssistantMessagePhaseTracker();
|
|
641
|
+
// Text of the newest assistant message this stream completed durably.
|
|
642
|
+
let latestStreamedAssistantText: string | null = null;
|
|
581
643
|
// Actual input tokens of the most recent model response this turn; the
|
|
582
644
|
// pre-read trigger for the NEXT turn. Persisted at every turn-end path.
|
|
583
645
|
throwIfWorkerShuttingDown();
|
|
@@ -589,7 +651,7 @@ export async function runTurnStreamAttempt(
|
|
|
589
651
|
let fallbackProviderRequestStartedAt: number | null = null;
|
|
590
652
|
let fallbackProviderRequestLifecycleStartedAt: number | null = null;
|
|
591
653
|
const recordFallbackProviderDispatchAtWire = async (): Promise<void> => {
|
|
592
|
-
await
|
|
654
|
+
await checkpointBeforeProviderDispatch();
|
|
593
655
|
if (
|
|
594
656
|
providerPublishesNativeRequestEvents ||
|
|
595
657
|
eventing.firstModelRequestPreparationRecorded ||
|
|
@@ -650,8 +712,7 @@ export async function runTurnStreamAttempt(
|
|
|
650
712
|
});
|
|
651
713
|
}
|
|
652
714
|
};
|
|
653
|
-
const ownedEstablished =
|
|
654
|
-
sandboxState.resolvedSandbox?.established ?? sandboxState.lazyOwnedSandbox;
|
|
715
|
+
const ownedEstablished = ownedTurnSandboxForAgent(sandboxState);
|
|
655
716
|
const runStreamOnce = async (): ReturnType<OpenGeniRuntime["runStream"]> => {
|
|
656
717
|
const eagerResolvedSandbox = sandboxState.resolvedSandbox;
|
|
657
718
|
// Eager owned sessions must settle the exact platform-setup provider
|
|
@@ -759,8 +820,8 @@ export async function runTurnStreamAttempt(
|
|
|
759
820
|
eventing.firstModelRequestPreparationStartedAt = performance.now();
|
|
760
821
|
eventing.firstModelRequestCheckpointAt = eventing.firstModelRequestPreparationStartedAt;
|
|
761
822
|
}
|
|
762
|
-
const
|
|
763
|
-
let
|
|
823
|
+
const streamInitializationStartedAt = performance.now();
|
|
824
|
+
let streamInitializationOutcome: "completed" | "failed" = "completed";
|
|
764
825
|
try {
|
|
765
826
|
// This histogram describes worker preparation until the first entry
|
|
766
827
|
// into the runtime. Lazy SDK request preparation and the durable
|
|
@@ -779,6 +840,8 @@ export async function runTurnStreamAttempt(
|
|
|
779
840
|
}
|
|
780
841
|
attempt.modelRequestStarted = true;
|
|
781
842
|
return await runtime.runStream(agent, runInput!, eventing.modelRunSettings, {
|
|
843
|
+
beforeModelRequest: modelCallAdmission.beforeModelRequest,
|
|
844
|
+
onModelResponse: modelCallAdmission.onModelResponse,
|
|
782
845
|
signal: runtimeCancellationSignal,
|
|
783
846
|
sandboxEnvironment,
|
|
784
847
|
onModelVisibleContext: async (snapshot) => {
|
|
@@ -885,6 +948,12 @@ export async function runTurnStreamAttempt(
|
|
|
885
948
|
...(!providerPublishesNativeRequestEvents
|
|
886
949
|
? {
|
|
887
950
|
onModelTransportStarted: recordFallbackProviderDispatchAtWire,
|
|
951
|
+
onModelTransportDispatched: (clock) => {
|
|
952
|
+
eventing.initialModelWireDispatch.record(
|
|
953
|
+
{ provider: streamProvider, dispatchId },
|
|
954
|
+
clock,
|
|
955
|
+
);
|
|
956
|
+
},
|
|
888
957
|
}
|
|
889
958
|
: {}),
|
|
890
959
|
...(eventing.toolCancellationFenceRef.current
|
|
@@ -894,15 +963,15 @@ export async function runTurnStreamAttempt(
|
|
|
894
963
|
: {}),
|
|
895
964
|
});
|
|
896
965
|
} catch (error) {
|
|
897
|
-
|
|
966
|
+
streamInitializationOutcome = "failed";
|
|
898
967
|
throw error;
|
|
899
968
|
} finally {
|
|
900
969
|
recordTurnStartupPhase(observability, {
|
|
901
|
-
phase: "
|
|
970
|
+
phase: "runtime_stream_initialization",
|
|
902
971
|
provider: turnExecutionPolicy.providerId,
|
|
903
972
|
backend: activeSandboxBackend ?? groupBoxBackend,
|
|
904
|
-
outcome:
|
|
905
|
-
durationSeconds: (performance.now() -
|
|
973
|
+
outcome: streamInitializationOutcome,
|
|
974
|
+
durationSeconds: (performance.now() - streamInitializationStartedAt) / 1_000,
|
|
906
975
|
});
|
|
907
976
|
}
|
|
908
977
|
};
|
|
@@ -914,7 +983,13 @@ export async function runTurnStreamAttempt(
|
|
|
914
983
|
if (leases.xai.lost) {
|
|
915
984
|
throw new Error("xAI credential lease expired before the model run");
|
|
916
985
|
}
|
|
917
|
-
|
|
986
|
+
try {
|
|
987
|
+
eventing.stream = await withProviderRequestContext(runStreamOnce);
|
|
988
|
+
} catch (error) {
|
|
989
|
+
modelCallAdmission.fail(error);
|
|
990
|
+
modelCallAdmission.close();
|
|
991
|
+
throw error;
|
|
992
|
+
}
|
|
918
993
|
// Bounded provider label for the streaming SLIs — the resolved registry
|
|
919
994
|
// provider id (or the built-in OpenAI/Azure provider), never a raw
|
|
920
995
|
// user-supplied model string.
|
|
@@ -960,6 +1035,7 @@ export async function runTurnStreamAttempt(
|
|
|
960
1035
|
attemptId: input.attemptId,
|
|
961
1036
|
dispatchId,
|
|
962
1037
|
executionGeneration: attempt.executionGeneration,
|
|
1038
|
+
...eventing.initialModelWireDispatch.payload({ provider: streamProvider, dispatchId }),
|
|
963
1039
|
},
|
|
964
1040
|
},
|
|
965
1041
|
]);
|
|
@@ -977,6 +1053,7 @@ export async function runTurnStreamAttempt(
|
|
|
977
1053
|
}
|
|
978
1054
|
await settleFallbackProviderFirstByte();
|
|
979
1055
|
let stableToolCallIdsToClear: string[] | null = null;
|
|
1056
|
+
let newlyDurableToolCallId: string | null = null;
|
|
980
1057
|
let completedCurrentToolBatch = false;
|
|
981
1058
|
let retainedScreenshotMetadata: RetainedArtifactMetadata | null = null;
|
|
982
1059
|
let normalizedSdkEvents: ReturnType<typeof normalizeSdkEvent> | null = null;
|
|
@@ -1046,6 +1123,10 @@ export async function runTurnStreamAttempt(
|
|
|
1046
1123
|
attemptId: input.attemptId,
|
|
1047
1124
|
dispatchId,
|
|
1048
1125
|
executionGeneration: attempt.executionGeneration,
|
|
1126
|
+
...eventing.initialModelWireDispatch.payload({
|
|
1127
|
+
provider: streamProvider,
|
|
1128
|
+
dispatchId,
|
|
1129
|
+
}),
|
|
1049
1130
|
},
|
|
1050
1131
|
},
|
|
1051
1132
|
]);
|
|
@@ -1067,35 +1148,22 @@ export async function runTurnStreamAttempt(
|
|
|
1067
1148
|
await historySink.reconcileConversationTruth();
|
|
1068
1149
|
turnLifecycleMetricsFor(observability).progress({ attemptId: input.attemptId });
|
|
1069
1150
|
modelCheckpointMemoryCollector.schedule(observability);
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
)
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
// the outer catch can end this segment gracefully with full
|
|
1084
|
-
// conversation context preserved for the post-top-up resume.
|
|
1085
|
-
let serializedRunState: string | null = null;
|
|
1086
|
-
try {
|
|
1087
|
-
serializedRunState = media.compactMediaRunState(
|
|
1088
|
-
String(eventing.stream.state.toString()),
|
|
1089
|
-
);
|
|
1090
|
-
} catch {
|
|
1091
|
-
serializedRunState = null;
|
|
1092
|
-
}
|
|
1093
|
-
throw new BudgetExhaustedError(
|
|
1094
|
-
limitError instanceof Error ? limitError.message : String(limitError),
|
|
1095
|
-
serializedRunState,
|
|
1096
|
-
);
|
|
1097
|
-
}
|
|
1151
|
+
await ensureRunAllowedBetweenModelCalls({
|
|
1152
|
+
settings,
|
|
1153
|
+
db,
|
|
1154
|
+
accountId: input.accountId,
|
|
1155
|
+
workspaceId: input.workspaceId,
|
|
1156
|
+
isExternallyBilledTurn: billingState.isExternallyBilledTurn,
|
|
1157
|
+
entitlements,
|
|
1158
|
+
chargesOpenGeniCredits: billingState.chargesOpenGeniCredits,
|
|
1159
|
+
countsTowardTokenCap: billingState.countsTowardTokenCap,
|
|
1160
|
+
initiatingHumanSubjectId: turn.initiatingHumanSubjectId,
|
|
1161
|
+
serializedRunState: () =>
|
|
1162
|
+
media.compactMediaRunState(String(eventing.stream!.state.toString())),
|
|
1163
|
+
});
|
|
1098
1164
|
}
|
|
1165
|
+
// Release only after both the debit and frozen-human admission finish.
|
|
1166
|
+
modelCallAdmission.settle(next.value);
|
|
1099
1167
|
const durableSdkEvent = generatedImageReceipt
|
|
1100
1168
|
? compactGeneratedImageSdkEvent(next.value, generatedImageReceipt)
|
|
1101
1169
|
: next.value;
|
|
@@ -1122,10 +1190,17 @@ export async function runTurnStreamAttempt(
|
|
|
1122
1190
|
currentToolBatchCallIds.add(pendingToolCall.callId);
|
|
1123
1191
|
if (toolCallProducesRetainableSessionImage(pendingToolCall.callName)) {
|
|
1124
1192
|
media.retainedSessionImageCallIds.add(pendingToolCall.callId);
|
|
1193
|
+
if (retainableBrowserScreenshotToolCall(pendingToolCall.callName)) {
|
|
1194
|
+
media.retainedSessionImageKindsByCallId.set(
|
|
1195
|
+
pendingToolCall.callId,
|
|
1196
|
+
"browser_screenshot",
|
|
1197
|
+
);
|
|
1198
|
+
}
|
|
1125
1199
|
}
|
|
1126
1200
|
}
|
|
1127
1201
|
const completedToolCall = completedToolCallFromSdkEvent(durableSdkEvent);
|
|
1128
1202
|
if (completedToolCall) {
|
|
1203
|
+
toolsExecuted = true;
|
|
1129
1204
|
retainedScreenshotMetadata =
|
|
1130
1205
|
media.retainedScreenshotReceiptsByCallId.get(completedToolCall.callId) ?? null;
|
|
1131
1206
|
const typedScreenshot = retainedScreenshotMetadata
|
|
@@ -1144,6 +1219,7 @@ export async function runTurnStreamAttempt(
|
|
|
1144
1219
|
toolCallId: completedToolCall.callId,
|
|
1145
1220
|
toolOutputId: completedToolCall.callId,
|
|
1146
1221
|
reason: "unsupported",
|
|
1222
|
+
kind: media.retainedSessionImageKindsByCallId.get(completedToolCall.callId),
|
|
1147
1223
|
});
|
|
1148
1224
|
media.retainedScreenshotReceiptsByCallId.set(
|
|
1149
1225
|
completedToolCall.callId,
|
|
@@ -1166,12 +1242,13 @@ export async function runTurnStreamAttempt(
|
|
|
1166
1242
|
toolCallId: typedScreenshot.callId,
|
|
1167
1243
|
toolOutputId: typedScreenshot.toolOutputId,
|
|
1168
1244
|
reason: "pending",
|
|
1245
|
+
kind: media.retainedSessionImageKindsByCallId.get(completedToolCall.callId),
|
|
1169
1246
|
});
|
|
1170
1247
|
media.retainedScreenshotReceiptsByCallId.set(
|
|
1171
1248
|
completedToolCall.callId,
|
|
1172
1249
|
retainedScreenshotMetadata,
|
|
1173
1250
|
);
|
|
1174
|
-
retainedScreenshotMetadata = await
|
|
1251
|
+
retainedScreenshotMetadata = await retainSessionScreenshot({
|
|
1175
1252
|
db,
|
|
1176
1253
|
objectStorage,
|
|
1177
1254
|
accountId: input.accountId,
|
|
@@ -1180,6 +1257,7 @@ export async function runTurnStreamAttempt(
|
|
|
1180
1257
|
turnId: activeTurnId,
|
|
1181
1258
|
attemptId: input.attemptId,
|
|
1182
1259
|
output: typedScreenshot,
|
|
1260
|
+
kind: media.retainedSessionImageKindsByCallId.get(completedToolCall.callId),
|
|
1183
1261
|
});
|
|
1184
1262
|
media.retainedScreenshotReceiptsByCallId.set(
|
|
1185
1263
|
completedToolCall.callId,
|
|
@@ -1190,6 +1268,7 @@ export async function runTurnStreamAttempt(
|
|
|
1190
1268
|
durableSdkEvent as typeof next.value,
|
|
1191
1269
|
retainedScreenshotMetadata
|
|
1192
1270
|
? {
|
|
1271
|
+
messagePhases,
|
|
1193
1272
|
toolOutputOverride: retainedScreenshotMetadata,
|
|
1194
1273
|
retainedOutputEvidence: retainedScreenshotMetadata.available
|
|
1195
1274
|
? retainedScreenshotMetadata
|
|
@@ -1198,7 +1277,7 @@ export async function runTurnStreamAttempt(
|
|
|
1198
1277
|
reason: retainedScreenshotMetadata.reason,
|
|
1199
1278
|
},
|
|
1200
1279
|
}
|
|
1201
|
-
: {},
|
|
1280
|
+
: { messagePhases },
|
|
1202
1281
|
);
|
|
1203
1282
|
const normalizedToolOutput = normalizedSdkEvents.find(
|
|
1204
1283
|
(event) =>
|
|
@@ -1246,6 +1325,7 @@ export async function runTurnStreamAttempt(
|
|
|
1246
1325
|
"turn attempt ended while recording a tool-call result",
|
|
1247
1326
|
);
|
|
1248
1327
|
}
|
|
1328
|
+
if (recorded.recorded) newlyDurableToolCallId = completedToolCall.callId;
|
|
1249
1329
|
const videoAcceptance = videoGenerationAcceptancesByCallId.get(completedToolCall.callId);
|
|
1250
1330
|
if (videoAcceptance && startVideoGenerationWorkflow) {
|
|
1251
1331
|
try {
|
|
@@ -1291,6 +1371,7 @@ export async function runTurnStreamAttempt(
|
|
|
1291
1371
|
durableSdkEvent as typeof next.value,
|
|
1292
1372
|
retainedScreenshotMetadata
|
|
1293
1373
|
? {
|
|
1374
|
+
messagePhases,
|
|
1294
1375
|
toolOutputOverride: retainedScreenshotMetadata,
|
|
1295
1376
|
retainedOutputEvidence: retainedScreenshotMetadata.available
|
|
1296
1377
|
? retainedScreenshotMetadata
|
|
@@ -1299,11 +1380,33 @@ export async function runTurnStreamAttempt(
|
|
|
1299
1380
|
reason: retainedScreenshotMetadata.reason,
|
|
1300
1381
|
},
|
|
1301
1382
|
}
|
|
1302
|
-
: {},
|
|
1383
|
+
: { messagePhases },
|
|
1303
1384
|
);
|
|
1304
1385
|
for (const event of normalized) {
|
|
1386
|
+
if (event.type === "agent.toolCall.created") {
|
|
1387
|
+
const preparedServers = eventing.preparedTools?.mcpServers ?? [];
|
|
1388
|
+
// Display metadata and the content-free analytics family are
|
|
1389
|
+
// event-copy enrichments only; the executable call is unchanged.
|
|
1390
|
+
event.payload = withToolCallFamily(
|
|
1391
|
+
preparedServers,
|
|
1392
|
+
runSettings.mcpServers,
|
|
1393
|
+
withMcpToolDisplayMetadata(preparedServers, event.payload),
|
|
1394
|
+
);
|
|
1395
|
+
}
|
|
1305
1396
|
streamTiming.onEvent(event.type);
|
|
1306
|
-
|
|
1397
|
+
if (event.type === "agent.toolCall.output") {
|
|
1398
|
+
const batcher = eventing.batcher;
|
|
1399
|
+
await withMcpCallIdentity((event.payload as { id: string }).id, () =>
|
|
1400
|
+
measureMcpPhase("event_persistence", () => batcher.push(event)),
|
|
1401
|
+
);
|
|
1402
|
+
} else {
|
|
1403
|
+
await eventing.batcher.push(event);
|
|
1404
|
+
}
|
|
1405
|
+
if (event.type === "agent.message.completed") {
|
|
1406
|
+
// Completed messages are structural: push returns once durable.
|
|
1407
|
+
latestStreamedAssistantText = (event.payload as { text: string }).text;
|
|
1408
|
+
latestAssistantMessageText = latestStreamedAssistantText;
|
|
1409
|
+
}
|
|
1307
1410
|
}
|
|
1308
1411
|
// Structural tool-output events await their durable append before
|
|
1309
1412
|
// push returns. The complete result is now retained in the event
|
|
@@ -1331,10 +1434,20 @@ export async function runTurnStreamAttempt(
|
|
|
1331
1434
|
}
|
|
1332
1435
|
for (const callId of stableToolCallIdsToClear) {
|
|
1333
1436
|
media.retainedSessionImageCallIds.delete(callId);
|
|
1437
|
+
media.retainedSessionImageKindsByCallId.delete(callId);
|
|
1334
1438
|
}
|
|
1335
1439
|
}
|
|
1440
|
+
if (newlyDurableToolCallId) {
|
|
1441
|
+
// The exact call/result receipt and structural output event are now
|
|
1442
|
+
// durable even when parallel SDK history is still non-monotonic.
|
|
1443
|
+
// Release only this result owner's completed foreground ops. A
|
|
1444
|
+
// missing/duplicate receipt cannot license new output collection;
|
|
1445
|
+
// the complete-turn hook remains its later durability boundary.
|
|
1446
|
+
await finalizeTurnOpStreamOps([newlyDurableToolCallId]);
|
|
1447
|
+
}
|
|
1336
1448
|
}
|
|
1337
1449
|
} catch (error) {
|
|
1450
|
+
modelCallAdmission.fail(error);
|
|
1338
1451
|
// Event processing can fail while SDK completion is still pending.
|
|
1339
1452
|
// Close this stream before any failure publication; a legitimate
|
|
1340
1453
|
// compaction retry may start a new, independently fenced generation.
|
|
@@ -1357,6 +1470,10 @@ export async function runTurnStreamAttempt(
|
|
|
1357
1470
|
attemptId: input.attemptId,
|
|
1358
1471
|
dispatchId,
|
|
1359
1472
|
executionGeneration: attempt.executionGeneration,
|
|
1473
|
+
...eventing.initialModelWireDispatch.payload({
|
|
1474
|
+
provider: streamProvider,
|
|
1475
|
+
dispatchId,
|
|
1476
|
+
}),
|
|
1360
1477
|
},
|
|
1361
1478
|
},
|
|
1362
1479
|
]);
|
|
@@ -1381,15 +1498,13 @@ export async function runTurnStreamAttempt(
|
|
|
1381
1498
|
await eventing.publish!([
|
|
1382
1499
|
{
|
|
1383
1500
|
type: "turn.startup.phase.failed",
|
|
1384
|
-
payload:
|
|
1385
|
-
phase: "model_preparation",
|
|
1386
|
-
durationMs: Math.round(durationMs),
|
|
1387
|
-
},
|
|
1501
|
+
payload: modelPreparationFailureEventPayload(error, durationMs),
|
|
1388
1502
|
},
|
|
1389
1503
|
]);
|
|
1390
1504
|
}
|
|
1391
1505
|
throw error;
|
|
1392
1506
|
} finally {
|
|
1507
|
+
modelCallAdmission.close();
|
|
1393
1508
|
if (!streamDone) {
|
|
1394
1509
|
// ReadableStream cancellation synchronously trips the Agents SDK's
|
|
1395
1510
|
// abort controller, but its returned promise may wait for an
|
|
@@ -1411,7 +1526,10 @@ export async function runTurnStreamAttempt(
|
|
|
1411
1526
|
// External Codemode stays reachable until finalization. Close wait
|
|
1412
1527
|
// admission before any terminal output/history decision, and drain an
|
|
1413
1528
|
// already-admitted wait before consulting the actual runner-yield latch.
|
|
1414
|
-
|
|
1529
|
+
// Drain trusted receipts before deciding whether an empty stream may need
|
|
1530
|
+
// a handoff. Do not terminally seal the attempt until that decision: the
|
|
1531
|
+
// one same-turn stream still uses the ordinary input-wait admission gate.
|
|
1532
|
+
await eventing.preparedTools?.inputWaitYield?.drainForHandoff(runtimeCancellationSignal);
|
|
1415
1533
|
if (
|
|
1416
1534
|
options.requireTerminalModelResponse &&
|
|
1417
1535
|
!eventing.preparedTools?.inputWaitYield?.yielded &&
|
|
@@ -1524,6 +1642,7 @@ export async function runTurnStreamAttempt(
|
|
|
1524
1642
|
}
|
|
1525
1643
|
}
|
|
1526
1644
|
if (eventing.stream.interruptions.length > 0) {
|
|
1645
|
+
await eventing.preparedTools?.inputWaitYield?.sealForSettlement(runtimeCancellationSignal);
|
|
1527
1646
|
await historySink.reconcileConversationTruth({ requireDurable: true });
|
|
1528
1647
|
const approvals = runtime.serializeApprovals(eventing.stream.interruptions);
|
|
1529
1648
|
const humanInputInterruptions =
|
|
@@ -1639,7 +1758,16 @@ export async function runTurnStreamAttempt(
|
|
|
1639
1758
|
? [
|
|
1640
1759
|
{
|
|
1641
1760
|
type: "session.requiresAction" as const,
|
|
1642
|
-
payload: {
|
|
1761
|
+
payload: {
|
|
1762
|
+
approvals: approvals.map((approval) =>
|
|
1763
|
+
withPublicApprovalFields(
|
|
1764
|
+
withMcpToolDisplayMetadata(
|
|
1765
|
+
eventing.preparedTools?.mcpServers ?? [],
|
|
1766
|
+
approval,
|
|
1767
|
+
),
|
|
1768
|
+
),
|
|
1769
|
+
),
|
|
1770
|
+
},
|
|
1643
1771
|
},
|
|
1644
1772
|
]
|
|
1645
1773
|
: []),
|
|
@@ -1671,6 +1799,77 @@ export async function runTurnStreamAttempt(
|
|
|
1671
1799
|
const finalOutput = String(
|
|
1672
1800
|
requireAgentStreamFinalOutput(eventing.stream.finalOutput, inputWaitYielded),
|
|
1673
1801
|
);
|
|
1802
|
+
const durableReplyFacts =
|
|
1803
|
+
!inputWaitYielded && finalOutput.trim().length === 0
|
|
1804
|
+
? await sessionTurnFinalReplyFacts(db, input.workspaceId, input.sessionId, activeTurnId)
|
|
1805
|
+
: { toolsExecuted: false, completedGoal: false };
|
|
1806
|
+
let emptyFinalReply = false;
|
|
1807
|
+
if (
|
|
1808
|
+
needsFinalReply({
|
|
1809
|
+
output: finalOutput,
|
|
1810
|
+
inputWaitYielded:
|
|
1811
|
+
inputWaitYielded || eventing.preparedTools?.inputWaitYield?.requested === true,
|
|
1812
|
+
interrupted: false, // interruption settlement returned above
|
|
1813
|
+
maintenance: turn.source === "compaction",
|
|
1814
|
+
toolsExecuted: toolsExecuted || finalReplyNudged || durableReplyFacts.toolsExecuted,
|
|
1815
|
+
completedGoal: durableReplyFacts.completedGoal,
|
|
1816
|
+
})
|
|
1817
|
+
) {
|
|
1818
|
+
await historySink.reconcileConversationTruth({ requireDurable: true });
|
|
1819
|
+
// Consult retained truth, including inactive compacted rows, so an
|
|
1820
|
+
// attempt replacement or compaction cannot spend this bound again.
|
|
1821
|
+
if (
|
|
1822
|
+
finalReplyNudged ||
|
|
1823
|
+
(await sessionTurnHasFinalReplyNudge(
|
|
1824
|
+
db,
|
|
1825
|
+
input.workspaceId,
|
|
1826
|
+
input.sessionId,
|
|
1827
|
+
activeTurnId,
|
|
1828
|
+
finalReplyNudge(activeTurnId).content[0]!.text,
|
|
1829
|
+
))
|
|
1830
|
+
) {
|
|
1831
|
+
// A second empty response is a delivery-quality notice, not failed
|
|
1832
|
+
// execution: preserve goal continuation and later machine-input wakes.
|
|
1833
|
+
emptyFinalReply = true;
|
|
1834
|
+
} else {
|
|
1835
|
+
const appended = await appendSessionHistoryItems(db, {
|
|
1836
|
+
accountId: input.accountId,
|
|
1837
|
+
workspaceId: input.workspaceId,
|
|
1838
|
+
sessionId: input.sessionId,
|
|
1839
|
+
turnId: activeTurnId,
|
|
1840
|
+
expectedExecutionGeneration: attempt.executionGeneration,
|
|
1841
|
+
expectedAttemptId: input.attemptId,
|
|
1842
|
+
items: [
|
|
1843
|
+
{
|
|
1844
|
+
position: await nextSessionHistoryPosition(db, input.workspaceId, input.sessionId),
|
|
1845
|
+
item: finalReplyNudge(activeTurnId),
|
|
1846
|
+
},
|
|
1847
|
+
],
|
|
1848
|
+
});
|
|
1849
|
+
if (!appended) throw new TurnAttemptFencedError("turn ended before final reply handoff");
|
|
1850
|
+
finalReplyNudged = true;
|
|
1851
|
+
await prepareRunAttemptInput();
|
|
1852
|
+
return "reply_nudge";
|
|
1853
|
+
}
|
|
1854
|
+
}
|
|
1855
|
+
await eventing.preparedTools?.inputWaitYield?.sealForSettlement(runtimeCancellationSignal);
|
|
1856
|
+
// The final output is the newest message this stream completed, already
|
|
1857
|
+
// durable with its provider identity and phase. A phase-less settlement
|
|
1858
|
+
// copy is published only when this stream did not complete that text.
|
|
1859
|
+
const finalOutputAlreadyCompleted = latestStreamedAssistantText === finalOutput;
|
|
1860
|
+
// A wait ends the turn with empty output; a human's message still gets
|
|
1861
|
+
// its answer recorded for unread attention and Slack.
|
|
1862
|
+
const reply = await inputWaitReply({
|
|
1863
|
+
inputWaitYielded,
|
|
1864
|
+
turn,
|
|
1865
|
+
latestAssistantMessageText,
|
|
1866
|
+
readLatestDurableTurnMessage: async () =>
|
|
1867
|
+
await latestDurableTurnMessageText(db, {
|
|
1868
|
+
workspaceId: input.workspaceId,
|
|
1869
|
+
sessionId: input.sessionId,
|
|
1870
|
+
turnId: turn.id,
|
|
1871
|
+
}),
|
|
1872
|
+
});
|
|
1674
1873
|
await historySink.reconcileConversationTruth({ requireDurable: true });
|
|
1675
1874
|
// Op-stream durability fence: the tool outputs are now durably in the
|
|
1676
1875
|
// history store (a redispatch would NOT re-execute them), so this
|
|
@@ -1683,10 +1882,17 @@ export async function runTurnStreamAttempt(
|
|
|
1683
1882
|
if (
|
|
1684
1883
|
!(await eventing.settle!({
|
|
1685
1884
|
events: [
|
|
1686
|
-
...(inputWaitYielded
|
|
1885
|
+
...(inputWaitYielded || finalOutputAlreadyCompleted
|
|
1687
1886
|
? []
|
|
1688
1887
|
: [{ type: "agent.message.completed" as const, payload: { text: finalOutput } }]),
|
|
1689
|
-
{
|
|
1888
|
+
{
|
|
1889
|
+
type: "turn.completed",
|
|
1890
|
+
payload: {
|
|
1891
|
+
output: finalOutput,
|
|
1892
|
+
...(reply === null ? {} : { reply }),
|
|
1893
|
+
...(emptyFinalReply ? { emptyFinalReply: true } : {}),
|
|
1894
|
+
},
|
|
1895
|
+
},
|
|
1690
1896
|
{ type: "session.status.changed", payload: { status: "idle" } },
|
|
1691
1897
|
],
|
|
1692
1898
|
turnStatus: "completed",
|
|
@@ -1746,7 +1952,11 @@ export async function runTurnStreamAttempt(
|
|
|
1746
1952
|
) {
|
|
1747
1953
|
return claimedResult({ status: "cancelled" });
|
|
1748
1954
|
}
|
|
1955
|
+
// Preparation may have spent the last allowance on a completed summary.
|
|
1956
|
+
// Neither the title sidecar nor ordinary inference may dispatch afterward.
|
|
1957
|
+
await revalidateModelCallAdmission();
|
|
1749
1958
|
if (
|
|
1959
|
+
turn.source !== "compaction" &&
|
|
1750
1960
|
generateSessionTitleInParallel &&
|
|
1751
1961
|
runtime.generateSessionTitle &&
|
|
1752
1962
|
!runtimeCancellationSignal.aborted
|
|
@@ -1759,18 +1969,16 @@ export async function runTurnStreamAttempt(
|
|
|
1759
1969
|
signal: runtimeCancellationSignal,
|
|
1760
1970
|
generate: async (signal) =>
|
|
1761
1971
|
await withSessionTitleProviderRequestContext(() =>
|
|
1762
|
-
runtime.generateSessionTitle!(
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
signal,
|
|
1773
|
-
}),
|
|
1972
|
+
runtime.generateSessionTitle!(
|
|
1973
|
+
runSettings,
|
|
1974
|
+
sessionTitlePrompt,
|
|
1975
|
+
sessionTitleGenerationOptions({
|
|
1976
|
+
resolvedModel,
|
|
1977
|
+
modelName: turnExecutionPolicy.upstreamModelId,
|
|
1978
|
+
serviceTier,
|
|
1979
|
+
signal,
|
|
1980
|
+
}),
|
|
1981
|
+
),
|
|
1774
1982
|
),
|
|
1775
1983
|
onError: (error) => {
|
|
1776
1984
|
observability.warn("parallel session title generation failed", {
|
|
@@ -1784,11 +1992,19 @@ export async function runTurnStreamAttempt(
|
|
|
1784
1992
|
}
|
|
1785
1993
|
try {
|
|
1786
1994
|
let retriedAfterCompaction = false;
|
|
1995
|
+
finalReplyNudged = await sessionTurnHasFinalReplyNudge(
|
|
1996
|
+
db,
|
|
1997
|
+
input.workspaceId,
|
|
1998
|
+
input.sessionId,
|
|
1999
|
+
activeTurnId,
|
|
2000
|
+
finalReplyNudge(activeTurnId).content[0]!.text,
|
|
2001
|
+
);
|
|
1787
2002
|
while (true) {
|
|
1788
2003
|
try {
|
|
1789
2004
|
const result = await runStreamAttempt({
|
|
1790
2005
|
requireTerminalModelResponse: retriedAfterCompaction,
|
|
1791
2006
|
});
|
|
2007
|
+
if (result === "reply_nudge") continue;
|
|
1792
2008
|
if (retriedAfterCompaction) {
|
|
1793
2009
|
observability.info("context compaction recovery succeeded after in-activity retry", {
|
|
1794
2010
|
sessionId: input.sessionId,
|
|
@@ -1822,6 +2038,7 @@ export async function runTurnStreamAttempt(
|
|
|
1822
2038
|
let compacted = false;
|
|
1823
2039
|
let compactionHandled = false;
|
|
1824
2040
|
let compactionFailureMessage: string | null = null;
|
|
2041
|
+
let compactionFailureError: unknown = null;
|
|
1825
2042
|
let compactionRequestCleared = false;
|
|
1826
2043
|
try {
|
|
1827
2044
|
const outcome = await forceContextCompaction(
|
|
@@ -1856,6 +2073,7 @@ export async function runTurnStreamAttempt(
|
|
|
1856
2073
|
{
|
|
1857
2074
|
clearRequestedCompaction: recoveryKind === "operator",
|
|
1858
2075
|
publishLiveEvents: publishCompactionLiveEvents,
|
|
2076
|
+
providerRejection: compactionProviderRejection(compactError),
|
|
1859
2077
|
},
|
|
1860
2078
|
);
|
|
1861
2079
|
compactionRequestCleared = landmark.requestConsumed;
|
|
@@ -1863,6 +2081,7 @@ export async function runTurnStreamAttempt(
|
|
|
1863
2081
|
await finishParallelSessionTitle();
|
|
1864
2082
|
const deferredSteer = await settleDeferredSteerAfterCompaction();
|
|
1865
2083
|
if (deferredSteer) return deferredSteer;
|
|
2084
|
+
compactionFailureError = compactError;
|
|
1866
2085
|
compactionFailureMessage = String(compactionFailureReasonFromError(compactError));
|
|
1867
2086
|
observability.warn("context compaction recovery compaction failed", {
|
|
1868
2087
|
sessionId: input.sessionId,
|
|
@@ -1880,13 +2099,9 @@ export async function runTurnStreamAttempt(
|
|
|
1880
2099
|
events: [
|
|
1881
2100
|
{
|
|
1882
2101
|
type: "turn.failed",
|
|
1883
|
-
payload: {
|
|
2102
|
+
payload: compactionFailureTurnEventPayload(compactionFailureError, {
|
|
1884
2103
|
error: errorMessage,
|
|
1885
|
-
|
|
1886
|
-
retryable: false,
|
|
1887
|
-
recovery: "user_message",
|
|
1888
|
-
compacted: false,
|
|
1889
|
-
},
|
|
2104
|
+
}),
|
|
1890
2105
|
},
|
|
1891
2106
|
{
|
|
1892
2107
|
type: "session.status.changed",
|
|
@@ -1919,6 +2134,27 @@ export async function runTurnStreamAttempt(
|
|
|
1919
2134
|
await finishParallelSessionTitle();
|
|
1920
2135
|
const deferredSteer = await settleDeferredSteerAfterCompaction();
|
|
1921
2136
|
if (deferredSteer) return deferredSteer;
|
|
2137
|
+
if (turn.source === "compaction") {
|
|
2138
|
+
const settled = await eventing.settle!({
|
|
2139
|
+
events: [
|
|
2140
|
+
{
|
|
2141
|
+
type: "turn.completed",
|
|
2142
|
+
payload: {
|
|
2143
|
+
maintenance: "context_compaction",
|
|
2144
|
+
result: compacted ? "compacted" : "already_applied",
|
|
2145
|
+
},
|
|
2146
|
+
},
|
|
2147
|
+
{ type: "session.status.changed", payload: { status: "idle" } },
|
|
2148
|
+
],
|
|
2149
|
+
turnStatus: "completed",
|
|
2150
|
+
sessionStatus: "idle",
|
|
2151
|
+
activeTurnId: null,
|
|
2152
|
+
});
|
|
2153
|
+
if (!settled) return claimedResult({ status: "cancelled" });
|
|
2154
|
+
control.turnMetricOutcome = "completed";
|
|
2155
|
+
control.activityStatus = "idle";
|
|
2156
|
+
return claimedResult({ status: "idle" });
|
|
2157
|
+
}
|
|
1922
2158
|
// Codex parity: compaction remains inside the same logical turn and
|
|
1923
2159
|
// the same activity. Rebuild the model-visible history from the
|
|
1924
2160
|
// durable replacement and continue the sampling loop; do not create
|