@opengeni/worker-bundle 1.0.1 → 2.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-turn/codex.d.ts +1 -1
- package/dist/activities/agent-turn/compaction-prep.d.ts +1 -5
- package/dist/activities/agent-turn/errors.d.ts +31 -5
- package/dist/activities/agent-turn/finalization-monitor.d.ts +17 -0
- package/dist/activities/agent-turn/finalization.d.ts +1 -1
- package/dist/activities/agent-turn/governance-model.d.ts +0 -2
- package/dist/activities/agent-turn/quiescence.d.ts +1 -0
- package/dist/activities/agent-turn/recovery-warning.d.ts +8 -0
- package/dist/activities/agent-turn/run-credentials.d.ts +0 -1
- package/dist/activities/agent-turn/sandbox-establish.d.ts +1 -1
- package/dist/activities/agent-turn/sandbox-route.d.ts +0 -20
- package/dist/activities/agent-turn/sandbox-runtime.d.ts +1 -1
- package/dist/activities/agent-turn/skill-remove.d.ts +14 -0
- package/dist/activities/agent-turn/skill-search.d.ts +1 -1
- package/dist/activities/agent-turn/stream-attempt.d.ts +1 -0
- package/dist/activities/agent-turn/tool-environment.d.ts +0 -4
- package/dist/activities/agent-turn/turn-context.d.ts +2 -0
- package/dist/activities/agent-turn/turn-sandbox-access.d.ts +3 -0
- package/dist/activities/codex-capacity.d.ts +6 -1
- package/dist/activities/codex-rotation.d.ts +1 -1
- package/dist/activities/context-compaction.d.ts +7 -1
- package/dist/activities/mcp-account-routes.d.ts +22 -0
- package/dist/activities/mcp-credentials.d.ts +12 -13
- package/dist/activities/mcp-operation-authority.d.ts +0 -5
- package/dist/activities/rig-verification.d.ts +2 -3
- package/dist/activities/sandbox-images.d.ts +1 -1
- package/dist/activities/sandbox-lease.d.ts +4 -3
- package/dist/activities/session-state.d.ts +57 -2
- package/dist/activities/types.d.ts +12 -3
- package/dist/{activities-control-HMFGSKC5.js → activities-control-BOLIY3H4.js} +366 -187
- package/dist/activities-control-BOLIY3H4.js.map +1 -0
- package/dist/activities-control.d.ts +110 -2
- package/dist/{activities-turn-AP67JADS.js → activities-turn-2B3WMHBB.js} +767 -471
- package/dist/activities-turn-2B3WMHBB.js.map +1 -0
- package/dist/activities.d.ts +110 -2
- package/dist/artifact-materializer-entry.js +5 -2
- package/dist/artifact-materializer-entry.js.map +1 -1
- package/dist/artifact-outbox-entry.js +2 -2
- package/dist/artifact-outbox-entry.js.map +1 -1
- package/dist/{chunk-A4XQWVZK.js → chunk-I7HKKMUJ.js} +77 -1
- package/dist/chunk-I7HKKMUJ.js.map +1 -0
- package/dist/{chunk-CYITU5UH.js → chunk-TVEE2UUC.js} +275 -146
- package/dist/chunk-TVEE2UUC.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/index.d.ts +55 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/observability-metrics.d.ts +11 -3
- package/dist/retained-process-diagnostics.d.ts +4 -0
- package/dist/sandbox-resume.d.ts +2 -12
- package/dist/sandbox-routing.d.ts +5 -3
- package/dist/sandbox-snapshot-diagnostics.d.ts +20 -0
- package/dist/warm-capture-holder.d.ts +3 -0
- package/dist/workflow-bundle.js +51 -11
- package/package.json +15 -15
- package/src/activities/agent-turn/agent-build.ts +42 -5
- package/src/activities/agent-turn/claim.ts +12 -0
- package/src/activities/agent-turn/codex-capacity.ts +26 -4
- package/src/activities/agent-turn/codex.ts +6 -2
- package/src/activities/agent-turn/compaction-prep.ts +53 -72
- package/src/activities/agent-turn/errors.ts +98 -10
- package/src/activities/agent-turn/failure-settlement.ts +49 -28
- package/src/activities/agent-turn/finalization-monitor.ts +121 -0
- package/src/activities/agent-turn/finalization.ts +79 -21
- package/src/activities/agent-turn/governance-model.ts +15 -19
- package/src/activities/agent-turn/history.ts +24 -10
- package/src/activities/agent-turn/quiescence.ts +3 -0
- package/src/activities/agent-turn/recovery-warning.ts +18 -0
- package/src/activities/agent-turn/run-credentials.ts +3 -7
- package/src/activities/agent-turn/run.ts +68 -52
- package/src/activities/agent-turn/sandbox-establish.ts +10 -2
- package/src/activities/agent-turn/sandbox-route.ts +0 -20
- package/src/activities/agent-turn/sandbox-runtime.ts +40 -7
- 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 +1 -1
- package/src/activities/agent-turn/skill-selection.ts +2 -0
- package/src/activities/agent-turn/skill-tools.ts +10 -5
- package/src/activities/agent-turn/stream-attempt.ts +38 -15
- package/src/activities/agent-turn/tool-environment.ts +44 -29
- package/src/activities/agent-turn/turn-context.ts +3 -0
- package/src/activities/agent-turn/turn-sandbox-access.ts +7 -1
- package/src/activities/capabilities.ts +17 -2
- package/src/activities/codex-capacity.ts +38 -9
- package/src/activities/codex-rotation.ts +18 -5
- package/src/activities/context-compaction.ts +26 -4
- package/src/activities/goals.ts +1 -0
- package/src/activities/google-drive-publication.ts +1 -3
- package/src/activities/mcp-account-routes.ts +139 -0
- package/src/activities/mcp-credentials.ts +83 -194
- package/src/activities/mcp-operation-authority.ts +16 -41
- package/src/activities/parent-wake.ts +8 -0
- package/src/activities/rig-verification.ts +38 -37
- package/src/activities/run-input.ts +25 -16
- package/src/activities/sandbox-images.ts +0 -1
- package/src/activities/sandbox-lease.ts +177 -44
- package/src/activities/scheduled-tasks.ts +118 -93
- package/src/activities/session-state.ts +83 -3
- package/src/activities/types.ts +18 -2
- package/src/activities/workflow-wake.ts +2 -17
- package/src/editable-artifact-materializer-service.ts +7 -3
- package/src/editable-artifact-outbox-service.ts +4 -4
- package/src/github-rest-mcp.ts +0 -1
- package/src/index.ts +2 -1
- package/src/observability-metrics.ts +105 -2
- package/src/personal-github-git-credentials.ts +0 -1
- package/src/pr-review-credentials.ts +0 -2
- package/src/retained-process-diagnostics.ts +50 -0
- package/src/sandbox-resume.ts +58 -73
- package/src/sandbox-routing.ts +44 -19
- package/src/sandbox-snapshot-diagnostics.ts +112 -0
- package/src/warm-capture-holder.ts +15 -0
- package/src/workflows/session.ts +64 -2
- 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/src/activities/agent-turn/knowledge-sources.ts +0 -86
- package/src/activities/packs.ts +0 -166
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
codexUsageLimitFailurePayload,
|
|
23
23
|
compactionFailureReason,
|
|
24
24
|
compactionFailureReasonFromError,
|
|
25
|
+
compactionFailureTurnEventPayload,
|
|
25
26
|
computeIdleDelayMs,
|
|
26
27
|
createKnowledgeSourceSyncActivities,
|
|
27
28
|
createModelHistoryAttachmentProjector,
|
|
@@ -56,7 +57,6 @@ import {
|
|
|
56
57
|
refreshExhaustedXaiQuota,
|
|
57
58
|
releaseTurnSandboxAfterWriterDrain,
|
|
58
59
|
requireAgentStreamFinalOutput,
|
|
59
|
-
resolveWorkspacePackRuntime,
|
|
60
60
|
resumeBoxForTurn,
|
|
61
61
|
rigProviderImageSourceImage,
|
|
62
62
|
routingEnabled,
|
|
@@ -68,7 +68,6 @@ import {
|
|
|
68
68
|
sandboxLifecycleTransitionDiagnostic,
|
|
69
69
|
sandboxRouteTransitionCode,
|
|
70
70
|
selectCodexCredentialLeaseForTurn,
|
|
71
|
-
settingsWithPackSandboxImage,
|
|
72
71
|
shouldRecoverCompactionProviderFailure,
|
|
73
72
|
shouldRunTurnEndWorkspacePersistence,
|
|
74
73
|
shouldStartPeriodicWorkspaceSnapshot,
|
|
@@ -87,7 +86,7 @@ import {
|
|
|
87
86
|
withFirstPartyTools,
|
|
88
87
|
wrapLazyTurnBoxWithRouting,
|
|
89
88
|
wrapTurnBoxWithRouting
|
|
90
|
-
} from "./chunk-
|
|
89
|
+
} from "./chunk-TVEE2UUC.js";
|
|
91
90
|
import {
|
|
92
91
|
StreamTimingMetrics,
|
|
93
92
|
makeMachineOpObserver,
|
|
@@ -107,13 +106,14 @@ import {
|
|
|
107
106
|
recordSessionEventAppendLatency,
|
|
108
107
|
recordSessionEventAppendPhase,
|
|
109
108
|
recordSessionEventPublishLatency,
|
|
109
|
+
recordToolPreparationPhase,
|
|
110
110
|
recordTurnSandboxEstablishPolicy,
|
|
111
111
|
recordTurnStartupMilestone,
|
|
112
112
|
recordTurnStartupPhase,
|
|
113
113
|
recordTurnWorkerPreparationTotal,
|
|
114
114
|
runtimeMetricsHooksForObservability,
|
|
115
115
|
turnLifecycleMetricsFor
|
|
116
|
-
} from "./chunk-
|
|
116
|
+
} from "./chunk-I7HKKMUJ.js";
|
|
117
117
|
import {
|
|
118
118
|
__export
|
|
119
119
|
} from "./chunk-PZ5AY32C.js";
|
|
@@ -121,64 +121,8 @@ import {
|
|
|
121
121
|
// src/activities-turn.ts
|
|
122
122
|
import { createProductionAgentRuntime, summarizeForCompaction as summarizeForCompaction2 } from "@opengeni/runtime";
|
|
123
123
|
|
|
124
|
-
// src/activities/agent-turn/knowledge-sources.ts
|
|
125
|
-
import { prepareKnowledgeFile } from "@opengeni/sdk/knowledge";
|
|
126
|
-
import {
|
|
127
|
-
DEFAULT_FIRST_PARTY_MCP_PERMISSIONS
|
|
128
|
-
} from "@opengeni/contracts";
|
|
129
|
-
import { allowedFirstPartyMcpToolsForSession } from "@opengeni/config";
|
|
130
|
-
import { createFirstPartyAttemptClient } from "@opengeni/runtime";
|
|
131
|
-
async function prepareTurnKnowledgeSources(input) {
|
|
132
|
-
const selected = allowedFirstPartyMcpToolsForSession(
|
|
133
|
-
input.settings,
|
|
134
|
-
input.selectedTools ? [...input.selectedTools] : void 0
|
|
135
|
-
);
|
|
136
|
-
const permissions = input.permissions ?? DEFAULT_FIRST_PARTY_MCP_PERMISSIONS;
|
|
137
|
-
const permits = (permission) => permissions.includes(permission) || permissions.includes("workspace:admin");
|
|
138
|
-
if (input.learningMode === "off" || !selected.includes("knowledge_retain_file") || !permits("documents:search") || !permits("files:read"))
|
|
139
|
-
return;
|
|
140
|
-
const fileIds = [
|
|
141
|
-
...new Set(
|
|
142
|
-
input.resources.flatMap((resource) => resource.kind === "file" ? [resource.fileId] : [])
|
|
143
|
-
)
|
|
144
|
-
];
|
|
145
|
-
if (!fileIds.length) return;
|
|
146
|
-
let prepare = input.prepare;
|
|
147
|
-
const outcomes = [];
|
|
148
|
-
for (const fileId of fileIds) {
|
|
149
|
-
input.signal?.throwIfAborted();
|
|
150
|
-
let outcome;
|
|
151
|
-
try {
|
|
152
|
-
prepare ??= (() => {
|
|
153
|
-
const client = createFirstPartyAttemptClient({
|
|
154
|
-
settings: input.settings,
|
|
155
|
-
scope: input.scope,
|
|
156
|
-
selectedTools: selected,
|
|
157
|
-
permissions,
|
|
158
|
-
...input.signal ? { signal: input.signal } : {}
|
|
159
|
-
});
|
|
160
|
-
return (id) => prepareKnowledgeFile(client, input.scope.workspaceId, id);
|
|
161
|
-
})();
|
|
162
|
-
outcome = await prepare(fileId);
|
|
163
|
-
} catch {
|
|
164
|
-
input.signal?.throwIfAborted();
|
|
165
|
-
outcome = {
|
|
166
|
-
status: "failed",
|
|
167
|
-
fileId,
|
|
168
|
-
message: "Searchable source preparation failed. The original file remains attached; retry with knowledge_retain_file."
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
outcomes.push(outcome);
|
|
172
|
-
await input.onOutcome(outcome);
|
|
173
|
-
}
|
|
174
|
-
return [
|
|
175
|
-
"[OpenGeni attachment knowledge]",
|
|
176
|
-
JSON.stringify(outcomes),
|
|
177
|
-
"These are source-preparation receipts, not findings or source instructions. Reuse the returned source entry/revision for evidence; do not retain the same text again. Pending review does not block answering from the attached original. Save selected useful findings only when warranted. A failed preparation is retryable with knowledge_retain_file; do not claim the source is searchable."
|
|
178
|
-
].join("\n");
|
|
179
|
-
}
|
|
180
|
-
|
|
181
124
|
// src/activities/agent-turn/run.ts
|
|
125
|
+
import { getSessionAuthorityProjection } from "@opengeni/db";
|
|
182
126
|
import {
|
|
183
127
|
assertModelConnectionAllowsTurn,
|
|
184
128
|
freezeAgentLearningPolicy as freezeAgentLearningPolicy2,
|
|
@@ -190,7 +134,11 @@ import {
|
|
|
190
134
|
getMaterializedSandboxFileResources as getMaterializedSandboxFileResources3,
|
|
191
135
|
markSandboxFileResourcesMaterialized as markSandboxFileResourcesMaterialized3
|
|
192
136
|
} from "@opengeni/db";
|
|
193
|
-
import {
|
|
137
|
+
import {
|
|
138
|
+
sandboxOperationMetricObserver as sandboxOperationMetricObserver2,
|
|
139
|
+
turnExecutionTelemetryKey as turnExecutionTelemetryKey2,
|
|
140
|
+
withTraceContext
|
|
141
|
+
} from "@opengeni/observability";
|
|
194
142
|
import {
|
|
195
143
|
REMOTE_COMPACTION_V2_BETA_FEATURE,
|
|
196
144
|
REMOTE_COMPACTION_V2_IMPLEMENTATION as REMOTE_COMPACTION_V2_IMPLEMENTATION2,
|
|
@@ -1226,7 +1174,7 @@ function acceptsPromptCacheKeyForTurn(resolvedModel) {
|
|
|
1226
1174
|
}
|
|
1227
1175
|
return resolvedModel.provider.builtin === true || resolvedModel.provider.kind === "codex-subscription";
|
|
1228
1176
|
}
|
|
1229
|
-
async function refreshCappedCodexUsageRows(db, settings, workspaceId, accounts, capacitySignals) {
|
|
1177
|
+
async function refreshCappedCodexUsageRows(db, settings, workspaceId, accounts, capacitySignals, acceptedTurnId) {
|
|
1230
1178
|
const now = /* @__PURE__ */ new Date();
|
|
1231
1179
|
const stale = accounts.filter(
|
|
1232
1180
|
(account) => account.status === "active" && codexAccountNeedsLiveCapacityRefresh(account, now)
|
|
@@ -1235,10 +1183,12 @@ async function refreshCappedCodexUsageRows(db, settings, workspaceId, accounts,
|
|
|
1235
1183
|
return accounts;
|
|
1236
1184
|
}
|
|
1237
1185
|
await refreshCodexUsageAndRepairCapacityWaiters(
|
|
1238
|
-
stale.map(
|
|
1186
|
+
stale.map(
|
|
1187
|
+
(account) => () => fetchCodexUsageForAccount(db, settings, workspaceId, account.id, void 0, acceptedTurnId)
|
|
1188
|
+
),
|
|
1239
1189
|
() => signalPendingCodexCapacityWakeTargets({ db, ...capacitySignals }, workspaceId)
|
|
1240
1190
|
);
|
|
1241
|
-
return listCodexAccountStatuses(db, workspaceId).catch(() => accounts);
|
|
1191
|
+
return listCodexAccountStatuses(db, workspaceId, acceptedTurnId).catch(() => accounts);
|
|
1242
1192
|
}
|
|
1243
1193
|
function codexCredentialLeaseDeadlineExpired(confirmedUntilMs, nowMs = performance.now()) {
|
|
1244
1194
|
return confirmedUntilMs === null || !Number.isFinite(confirmedUntilMs) || confirmedUntilMs <= nowMs;
|
|
@@ -3180,6 +3130,7 @@ import { sandboxStateEntryFromRunState } from "@opengeni/runtime";
|
|
|
3180
3130
|
// src/activities/agent-turn/history.ts
|
|
3181
3131
|
import {
|
|
3182
3132
|
normalizeProtocolJsonValue,
|
|
3133
|
+
TURN_OPERATIONAL_NOTICE_PREFIX,
|
|
3183
3134
|
sanitizeHistoryItemsForModel,
|
|
3184
3135
|
toolCallIdFromSdkItem
|
|
3185
3136
|
} from "@opengeni/runtime";
|
|
@@ -3192,7 +3143,8 @@ function historyRowsToAppend(rawHistory, persistedHistoryCount, nextPosition = p
|
|
|
3192
3143
|
const rows = [];
|
|
3193
3144
|
for (const [offset, item] of modelReady.slice(persistedHistoryCount).entries()) {
|
|
3194
3145
|
if (item.type === "message" && item.role === "system") {
|
|
3195
|
-
|
|
3146
|
+
const content = typeof item.content === "string" ? item.content : Array.isArray(item.content) ? item.content.map((part) => part.text ?? "").join("") : "";
|
|
3147
|
+
if (!content.startsWith(TURN_OPERATIONAL_NOTICE_PREFIX)) continue;
|
|
3196
3148
|
}
|
|
3197
3149
|
rows.push({
|
|
3198
3150
|
position: nextPosition + rows.length,
|
|
@@ -3248,7 +3200,9 @@ function pendingToolCallFromSdkEvent(event) {
|
|
|
3248
3200
|
return null;
|
|
3249
3201
|
}
|
|
3250
3202
|
const raw = item.rawItem;
|
|
3251
|
-
|
|
3203
|
+
const providerData = raw.providerData;
|
|
3204
|
+
if (raw.type === "hosted_tool_call" && raw.name !== "mcp_approval_request" && providerData?.type !== "mcp_approval_request" && (raw.status === "completed" || raw.name === "image_generation_call"))
|
|
3205
|
+
return null;
|
|
3252
3206
|
const callId = toolCallIdFromSdkItem(raw) ?? raw.id;
|
|
3253
3207
|
const callType = raw.type;
|
|
3254
3208
|
if (typeof callId !== "string" || callId.length === 0 || typeof callType !== "string") {
|
|
@@ -3574,6 +3528,7 @@ function createTurnContext(input) {
|
|
|
3574
3528
|
publishedRunCredentialNotices: /* @__PURE__ */ new Set()
|
|
3575
3529
|
},
|
|
3576
3530
|
eventing: {
|
|
3531
|
+
heartbeatDetails: null,
|
|
3577
3532
|
heartbeatTimer: void 0,
|
|
3578
3533
|
batcher: null,
|
|
3579
3534
|
preparedTools: null,
|
|
@@ -3617,7 +3572,7 @@ function createTurnContext(input) {
|
|
|
3617
3572
|
import {
|
|
3618
3573
|
commitSessionAttemptQuiescence,
|
|
3619
3574
|
listPendingSessionTurns,
|
|
3620
|
-
|
|
3575
|
+
recordCodexAccountUsageForFinalization,
|
|
3621
3576
|
releaseCodexCredentialLease,
|
|
3622
3577
|
releaseXaiCredentialLease,
|
|
3623
3578
|
updateXaiQuotaMetadata
|
|
@@ -3627,6 +3582,109 @@ import { sandboxLeaseTelemetryKey } from "@opengeni/observability";
|
|
|
3627
3582
|
import { clearRunCredentialsForAttempt } from "@opengeni/runtime";
|
|
3628
3583
|
import { fetchXaiSubscriptionQuota } from "@opengeni/xai-subscription";
|
|
3629
3584
|
|
|
3585
|
+
// src/activities/agent-turn/finalization-monitor.ts
|
|
3586
|
+
var TURN_FINALIZATION_STAGES = [
|
|
3587
|
+
"tool_writers",
|
|
3588
|
+
"credential_renewals",
|
|
3589
|
+
"credential_cleanup",
|
|
3590
|
+
"quiescence_receipt",
|
|
3591
|
+
"event_flush",
|
|
3592
|
+
"provider_leases",
|
|
3593
|
+
"workspace_capture",
|
|
3594
|
+
"tool_close",
|
|
3595
|
+
"sandbox_provisioning",
|
|
3596
|
+
"sandbox_rotation",
|
|
3597
|
+
"workspace_snapshot",
|
|
3598
|
+
"sandbox_release"
|
|
3599
|
+
];
|
|
3600
|
+
var INFLIGHT = {
|
|
3601
|
+
name: "opengeni_turn_finalization_inflight",
|
|
3602
|
+
help: "Physical turn finalizers currently waiting in each cleanup stage."
|
|
3603
|
+
};
|
|
3604
|
+
var SLOW_STAGES = {
|
|
3605
|
+
name: "opengeni_turn_finalization_slow_total",
|
|
3606
|
+
help: "Turn cleanup stages observed to exceed thirty seconds."
|
|
3607
|
+
};
|
|
3608
|
+
var initialized = /* @__PURE__ */ new WeakSet();
|
|
3609
|
+
function diagnose(operation) {
|
|
3610
|
+
try {
|
|
3611
|
+
operation();
|
|
3612
|
+
} catch {
|
|
3613
|
+
}
|
|
3614
|
+
}
|
|
3615
|
+
function startTurnFinalizationMonitor(input) {
|
|
3616
|
+
const { observability, details } = input;
|
|
3617
|
+
if (!initialized.has(observability)) {
|
|
3618
|
+
for (const stage2 of TURN_FINALIZATION_STAGES) {
|
|
3619
|
+
diagnose(() => observability.incrementGauge({ ...INFLIGHT, labels: { stage: stage2 }, amount: 0 }));
|
|
3620
|
+
diagnose(
|
|
3621
|
+
() => observability.incrementCounter({ ...SLOW_STAGES, labels: { stage: stage2 }, amount: 0 })
|
|
3622
|
+
);
|
|
3623
|
+
}
|
|
3624
|
+
initialized.add(observability);
|
|
3625
|
+
}
|
|
3626
|
+
let stage = null;
|
|
3627
|
+
let disarm = () => {
|
|
3628
|
+
};
|
|
3629
|
+
let stopped = false;
|
|
3630
|
+
let slowTimer;
|
|
3631
|
+
const leave = () => {
|
|
3632
|
+
disarm();
|
|
3633
|
+
clearTimeout(slowTimer);
|
|
3634
|
+
if (stage) {
|
|
3635
|
+
const previous = stage;
|
|
3636
|
+
diagnose(
|
|
3637
|
+
() => observability.incrementGauge({ ...INFLIGHT, labels: { stage: previous }, amount: -1 })
|
|
3638
|
+
);
|
|
3639
|
+
}
|
|
3640
|
+
stage = null;
|
|
3641
|
+
};
|
|
3642
|
+
return {
|
|
3643
|
+
enter(next) {
|
|
3644
|
+
if (stopped || stage === next) return;
|
|
3645
|
+
leave();
|
|
3646
|
+
stage = next;
|
|
3647
|
+
details.phase = "finalizing";
|
|
3648
|
+
details.finalizationStage = next;
|
|
3649
|
+
details.finalizationStageStartedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3650
|
+
diagnose(() => observability.incrementGauge({ ...INFLIGHT, labels: { stage: next } }));
|
|
3651
|
+
disarm = armTurnQuiescenceWatchdog({
|
|
3652
|
+
enabled: true,
|
|
3653
|
+
...input.timeoutMs === void 0 ? {} : { timeoutMs: input.timeoutMs },
|
|
3654
|
+
onTimeout: () => {
|
|
3655
|
+
try {
|
|
3656
|
+
observability.error("turn finalization stalled; containing worker", {
|
|
3657
|
+
surface: "turn_finalization",
|
|
3658
|
+
outcome: "containment",
|
|
3659
|
+
reason: next
|
|
3660
|
+
});
|
|
3661
|
+
} catch {
|
|
3662
|
+
}
|
|
3663
|
+
},
|
|
3664
|
+
terminateWorker: input.terminateWorker
|
|
3665
|
+
});
|
|
3666
|
+
slowTimer = setTimeout(
|
|
3667
|
+
() => diagnose(() => {
|
|
3668
|
+
observability.incrementCounter({ ...SLOW_STAGES, labels: { stage: next } });
|
|
3669
|
+
observability.warn("turn finalization is taking longer than expected", {
|
|
3670
|
+
surface: "turn_finalization",
|
|
3671
|
+
outcome: "slow",
|
|
3672
|
+
reason: next
|
|
3673
|
+
});
|
|
3674
|
+
}),
|
|
3675
|
+
input.slowAfterMs ?? 3e4
|
|
3676
|
+
);
|
|
3677
|
+
slowTimer.unref?.();
|
|
3678
|
+
diagnose(() => input.heartbeat(details));
|
|
3679
|
+
},
|
|
3680
|
+
stop() {
|
|
3681
|
+
if (stopped) return;
|
|
3682
|
+
stopped = true;
|
|
3683
|
+
leave();
|
|
3684
|
+
}
|
|
3685
|
+
};
|
|
3686
|
+
}
|
|
3687
|
+
|
|
3630
3688
|
// src/activities/workspace-capture.ts
|
|
3631
3689
|
import { createHash as createHash6 } from "crypto";
|
|
3632
3690
|
import {
|
|
@@ -4452,6 +4510,35 @@ async function buildTreeIndex(svc, startedAt, signal) {
|
|
|
4452
4510
|
|
|
4453
4511
|
// src/activities/agent-turn/finalization.ts
|
|
4454
4512
|
async function finalizeTurnAttempt(deps) {
|
|
4513
|
+
const details = deps.eventing.heartbeatDetails ?? {
|
|
4514
|
+
sessionId: deps.input.sessionId,
|
|
4515
|
+
turnId: deps.attempt.turnId,
|
|
4516
|
+
opAcks: {}
|
|
4517
|
+
};
|
|
4518
|
+
deps.eventing.heartbeatDetails = details;
|
|
4519
|
+
if (deps.eventing.heartbeatTimer) clearInterval(deps.eventing.heartbeatTimer);
|
|
4520
|
+
deps.eventing.heartbeatTimer = startActivityHeartbeat(deps.activityContext, details);
|
|
4521
|
+
const monitor = startTurnFinalizationMonitor({
|
|
4522
|
+
observability: deps.observability,
|
|
4523
|
+
details,
|
|
4524
|
+
heartbeat: (value) => {
|
|
4525
|
+
try {
|
|
4526
|
+
deps.activityContext?.heartbeat({ ...value, at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
4527
|
+
} catch {
|
|
4528
|
+
}
|
|
4529
|
+
},
|
|
4530
|
+
terminateWorker: () => process.exit(1)
|
|
4531
|
+
});
|
|
4532
|
+
try {
|
|
4533
|
+
monitor.enter("tool_writers");
|
|
4534
|
+
await finalizeTurnAttemptSteps(deps, monitor);
|
|
4535
|
+
} finally {
|
|
4536
|
+
monitor.stop();
|
|
4537
|
+
if (deps.eventing.heartbeatTimer) clearInterval(deps.eventing.heartbeatTimer);
|
|
4538
|
+
deps.eventing.heartbeatTimer = void 0;
|
|
4539
|
+
}
|
|
4540
|
+
}
|
|
4541
|
+
async function finalizeTurnAttemptSteps(deps, monitor) {
|
|
4455
4542
|
const {
|
|
4456
4543
|
input,
|
|
4457
4544
|
settings,
|
|
@@ -4492,17 +4579,6 @@ async function finalizeTurnAttempt(deps) {
|
|
|
4492
4579
|
let finalizationError;
|
|
4493
4580
|
let physicalToolQuiescenceConfirmed = !control.acknowledgeQuiescence;
|
|
4494
4581
|
let quiescenceReceiptOrProofDurable = !control.acknowledgeQuiescence;
|
|
4495
|
-
const disarmQuiescenceWatchdog = armTurnQuiescenceWatchdog({
|
|
4496
|
-
enabled: control.acknowledgeQuiescence,
|
|
4497
|
-
onTimeout: () => {
|
|
4498
|
-
observability.error("turn quiescence drain exceeded hard containment deadline", {
|
|
4499
|
-
"opengeni.session_id": input.sessionId,
|
|
4500
|
-
"opengeni.turn_id": attempt.turnId ?? "",
|
|
4501
|
-
"opengeni.attempt_id": input.attemptId
|
|
4502
|
-
});
|
|
4503
|
-
},
|
|
4504
|
-
terminateWorker: () => process.exit(1)
|
|
4505
|
-
});
|
|
4506
4582
|
const finalizerSignal = turnFinalizerCancellationSignal(
|
|
4507
4583
|
cancellationSignal,
|
|
4508
4584
|
control.activityStatus
|
|
@@ -4539,12 +4615,14 @@ async function finalizeTurnAttempt(deps) {
|
|
|
4539
4615
|
// and durably settled before workspace capture. Only receipt
|
|
4540
4616
|
// publication remains conditional on acknowledgeQuiescence.
|
|
4541
4617
|
toolCancellationFence,
|
|
4618
|
+
onStage: monitor.enter,
|
|
4542
4619
|
cancellationReason: cancellationSignal?.reason ?? new Error("TURN_ATTEMPT_FINALIZED"),
|
|
4543
4620
|
gitCredentialRenewals: gitRenewalsToStop,
|
|
4544
4621
|
codemodeTokenRenewal: codemodeRenewalToStop,
|
|
4545
4622
|
runCredentialRenewal: runRenewalToStop
|
|
4546
4623
|
});
|
|
4547
4624
|
if (credentialSessionToClear) {
|
|
4625
|
+
monitor.enter("credential_cleanup");
|
|
4548
4626
|
const clearAttemptCredentials = async () => await clearRunCredentialsForAttempt(credentialSessionToClear, {
|
|
4549
4627
|
sessionId: input.sessionId,
|
|
4550
4628
|
attemptId: input.attemptId,
|
|
@@ -4574,6 +4652,7 @@ async function finalizeTurnAttempt(deps) {
|
|
|
4574
4652
|
physicalToolQuiescenceConfirmed = true;
|
|
4575
4653
|
}
|
|
4576
4654
|
if (control.acknowledgeQuiescence && physicalToolQuiescenceConfirmed) {
|
|
4655
|
+
monitor.enter("quiescence_receipt");
|
|
4577
4656
|
const proof = {
|
|
4578
4657
|
accountId: input.accountId,
|
|
4579
4658
|
workspaceId: input.workspaceId,
|
|
@@ -4614,6 +4693,7 @@ async function finalizeTurnAttempt(deps) {
|
|
|
4614
4693
|
signalProof: signalSessionAttemptQuiesced,
|
|
4615
4694
|
heartbeat: (deliveryAttempt, retryMs) => {
|
|
4616
4695
|
activityContext?.heartbeat({
|
|
4696
|
+
...eventing.heartbeatDetails,
|
|
4617
4697
|
phase: "quiescence-proof-delivery",
|
|
4618
4698
|
sessionId: input.sessionId,
|
|
4619
4699
|
attemptId: input.attemptId,
|
|
@@ -4646,7 +4726,6 @@ async function finalizeTurnAttempt(deps) {
|
|
|
4646
4726
|
}
|
|
4647
4727
|
});
|
|
4648
4728
|
quiescenceReceiptOrProofDurable = true;
|
|
4649
|
-
disarmQuiescenceWatchdog();
|
|
4650
4729
|
if (recoveryMode === "signal") {
|
|
4651
4730
|
observability.info("agent turn quiescence proof handed to workflow recovery", {
|
|
4652
4731
|
"opengeni.session_id": input.sessionId,
|
|
@@ -4656,6 +4735,7 @@ async function finalizeTurnAttempt(deps) {
|
|
|
4656
4735
|
});
|
|
4657
4736
|
}
|
|
4658
4737
|
}
|
|
4738
|
+
monitor.enter("event_flush");
|
|
4659
4739
|
const machineOpEvents = machineOpObserver.drainEvents();
|
|
4660
4740
|
if (machineOpEvents.length > 0 && attempt.turnId && attempt.executionGeneration > 0) {
|
|
4661
4741
|
await waitForTurnFinalizerStep(
|
|
@@ -4678,14 +4758,24 @@ async function finalizeTurnAttempt(deps) {
|
|
|
4678
4758
|
finalizerSignal
|
|
4679
4759
|
);
|
|
4680
4760
|
}
|
|
4761
|
+
monitor.enter("provider_leases");
|
|
4681
4762
|
if (providerTurn.effectiveCodexCredentialId) {
|
|
4682
|
-
if (providerTurn.latestCodexUsage) {
|
|
4763
|
+
if (providerTurn.latestCodexUsage && attempt.turnId && leases.codex.held && leases.codex.holderId && leases.codex.generation !== null && providerTurn.effectiveCodexCredentialVersion !== null) {
|
|
4683
4764
|
const usageMutation = await waitForTurnFinalizerStep(
|
|
4684
|
-
|
|
4765
|
+
recordCodexAccountUsageForFinalization(
|
|
4685
4766
|
db,
|
|
4686
4767
|
input.workspaceId,
|
|
4687
4768
|
providerTurn.effectiveCodexCredentialId,
|
|
4688
|
-
providerTurn.latestCodexUsage
|
|
4769
|
+
providerTurn.latestCodexUsage,
|
|
4770
|
+
{
|
|
4771
|
+
turnId: attempt.turnId,
|
|
4772
|
+
sessionId: input.sessionId,
|
|
4773
|
+
attemptId: input.attemptId,
|
|
4774
|
+
executionGeneration: attempt.executionGeneration,
|
|
4775
|
+
holderId: leases.codex.holderId,
|
|
4776
|
+
generation: leases.codex.generation,
|
|
4777
|
+
credentialVersion: providerTurn.effectiveCodexCredentialVersion
|
|
4778
|
+
}
|
|
4689
4779
|
).catch(() => null),
|
|
4690
4780
|
finalizerSignal
|
|
4691
4781
|
);
|
|
@@ -4760,6 +4850,7 @@ async function finalizeTurnAttempt(deps) {
|
|
|
4760
4850
|
deadlineRotationRequested: sandboxState.deadlineRotationRequested
|
|
4761
4851
|
});
|
|
4762
4852
|
if (settings.workspaceCaptureEnabled && runTurnEndPersistence && attempt.turnId && sandboxState.resolvedSandbox && sandboxState.setupBoxSession && sandboxState.sandboxGroupId) {
|
|
4853
|
+
monitor.enter("workspace_capture");
|
|
4763
4854
|
sandboxState.turnEndCaptureInProgress = true;
|
|
4764
4855
|
const captureSandbox = sandboxState.resolvedSandbox;
|
|
4765
4856
|
const captureSession = sandboxState.setupBoxSession;
|
|
@@ -4804,6 +4895,7 @@ async function finalizeTurnAttempt(deps) {
|
|
|
4804
4895
|
}
|
|
4805
4896
|
});
|
|
4806
4897
|
}
|
|
4898
|
+
monitor.enter("tool_close");
|
|
4807
4899
|
eventing.toolPreparationClosing = true;
|
|
4808
4900
|
if (eventing.toolPreparationReady) {
|
|
4809
4901
|
await waitForTurnFinalizerStep(
|
|
@@ -4824,9 +4916,7 @@ async function finalizeTurnAttempt(deps) {
|
|
|
4824
4916
|
finalizerSignal
|
|
4825
4917
|
);
|
|
4826
4918
|
}
|
|
4827
|
-
|
|
4828
|
-
clearInterval(eventing.heartbeatTimer);
|
|
4829
|
-
}
|
|
4919
|
+
monitor.enter("sandbox_provisioning");
|
|
4830
4920
|
if (sandboxState.turnSandboxProvisioner?.hasStarted()) {
|
|
4831
4921
|
await waitForTurnFinalizerStep(
|
|
4832
4922
|
sandboxState.turnSandboxProvisioner.waitForSettled(3e4),
|
|
@@ -4846,15 +4936,23 @@ async function finalizeTurnAttempt(deps) {
|
|
|
4846
4936
|
if (sandboxState.leaseHeartbeatTimer) {
|
|
4847
4937
|
stopLeaseHeartbeat();
|
|
4848
4938
|
}
|
|
4939
|
+
monitor.enter("sandbox_rotation");
|
|
4849
4940
|
if (sandboxState.rotationPreemptionInFlight) {
|
|
4850
4941
|
await sandboxState.rotationPreemptionInFlight.catch(() => void 0);
|
|
4851
4942
|
}
|
|
4943
|
+
monitor.enter("workspace_snapshot");
|
|
4852
4944
|
await drainInFlightWarmSnapshot();
|
|
4853
4945
|
if (sandboxState.resolvedSandbox) {
|
|
4854
4946
|
const settledTurnId = attempt.turnId;
|
|
4855
4947
|
if (runTurnEndPersistence && sandboxState.setupBoxSession && sandboxState.sandboxGroupId && settledTurnId) {
|
|
4856
4948
|
const snapshot = maybePersistWarmWorkspaceSnapshot(
|
|
4857
|
-
{
|
|
4949
|
+
{
|
|
4950
|
+
db,
|
|
4951
|
+
settings,
|
|
4952
|
+
objectStorage,
|
|
4953
|
+
sandboxMetrics: runtimeMetricsHooksForObservability(observability),
|
|
4954
|
+
observability
|
|
4955
|
+
},
|
|
4858
4956
|
{
|
|
4859
4957
|
accountId: input.accountId,
|
|
4860
4958
|
workspaceId: input.workspaceId,
|
|
@@ -4887,10 +4985,13 @@ async function finalizeTurnAttempt(deps) {
|
|
|
4887
4985
|
);
|
|
4888
4986
|
} finally {
|
|
4889
4987
|
stopLeaseHeartbeat();
|
|
4988
|
+
monitor.enter("sandbox_rotation");
|
|
4890
4989
|
if (sandboxState.rotationPreemptionInFlight) {
|
|
4891
4990
|
await sandboxState.rotationPreemptionInFlight.catch(() => void 0);
|
|
4892
4991
|
}
|
|
4992
|
+
monitor.enter("workspace_snapshot");
|
|
4893
4993
|
await drainInFlightWarmSnapshot();
|
|
4994
|
+
monitor.enter("sandbox_release");
|
|
4894
4995
|
const sandboxReleaseTargets = new Set(sandboxState.lateSandboxesAwaitingWriterDrain);
|
|
4895
4996
|
sandboxState.lateSandboxesAwaitingWriterDrain.clear();
|
|
4896
4997
|
if (sandboxState.resolvedSandbox) {
|
|
@@ -5767,6 +5868,10 @@ function acceptedCodexPolicySnapshot(providerTurn) {
|
|
|
5767
5868
|
return providerTurn.codexPolicySnapshot;
|
|
5768
5869
|
}
|
|
5769
5870
|
async function settleTurnFailure(deps) {
|
|
5871
|
+
if (deps.settings.environment === "local" && deps.error instanceof Error) {
|
|
5872
|
+
const locations = (deps.error.stack ?? "").split("\n").slice(1).flatMap((line) => line.match(/(?:apps|packages)\/[A-Za-z0-9_./-]+:\d+:\d+/g) ?? []).slice(0, 8);
|
|
5873
|
+
console.error(JSON.stringify({ message: "Local turn failure source locations", locations }));
|
|
5874
|
+
}
|
|
5770
5875
|
const {
|
|
5771
5876
|
error: error51,
|
|
5772
5877
|
input,
|
|
@@ -5791,6 +5896,25 @@ async function settleTurnFailure(deps) {
|
|
|
5791
5896
|
acknowledgeLostAttemptOwnership,
|
|
5792
5897
|
acknowledgeRecoveryQuiescence
|
|
5793
5898
|
} = deps;
|
|
5899
|
+
if (isSessionEventPersistenceError2(error51)) {
|
|
5900
|
+
try {
|
|
5901
|
+
const diagnosticId = observability.recordFailureDiagnostic({
|
|
5902
|
+
code: error51.details.code,
|
|
5903
|
+
stage: error51.details.stage === "session_events.append_generic" ? "session_events.append_generic" : error51.details.stage === "session_events.append_for_turn_attempt" ? "session_events.append_for_turn_attempt" : error51.details.stage === "session_attempts.claim" ? "session_attempts.claim" : "failure_settlement",
|
|
5904
|
+
retryDecision: error51.details.retryOutcome,
|
|
5905
|
+
error: error51,
|
|
5906
|
+
sessionId: input.sessionId,
|
|
5907
|
+
...attempt.turnId ? { turnId: attempt.turnId } : {},
|
|
5908
|
+
attemptId: input.attemptId,
|
|
5909
|
+
attempts: error51.details.attempts,
|
|
5910
|
+
eventTypes: error51.details.eventTypes,
|
|
5911
|
+
sqlState: error51.details.sqlState,
|
|
5912
|
+
...error51.details.database.constraint ? { constraint: error51.details.database.constraint } : {}
|
|
5913
|
+
});
|
|
5914
|
+
observability.error("session event persistence failed", { correlationId: diagnosticId });
|
|
5915
|
+
} catch {
|
|
5916
|
+
}
|
|
5917
|
+
}
|
|
5794
5918
|
const recoveryTurnId = attempt.turnId;
|
|
5795
5919
|
const lifecycleTransition = sandboxLifecycleTransitionDiagnostic(error51);
|
|
5796
5920
|
const leaseControlError = error51 instanceof SandboxLeaseSupersededError ? error51 : lifecycleTransition;
|
|
@@ -6145,7 +6269,9 @@ async function settleTurnFailure(deps) {
|
|
|
6145
6269
|
labels: { workspace_key: codexWorkspaceKey, outcome: "completed" }
|
|
6146
6270
|
});
|
|
6147
6271
|
const now = /* @__PURE__ */ new Date();
|
|
6148
|
-
const before = await listCodexAccountStatuses2(db, input.workspaceId).catch(
|
|
6272
|
+
const before = await listCodexAccountStatuses2(db, input.workspaceId, attempt.turnId).catch(
|
|
6273
|
+
() => []
|
|
6274
|
+
);
|
|
6149
6275
|
const servingCached = before.find(
|
|
6150
6276
|
(account) => account.id === providerTurn.effectiveCodexCredentialId
|
|
6151
6277
|
);
|
|
@@ -6289,7 +6415,7 @@ async function settleTurnFailure(deps) {
|
|
|
6289
6415
|
}
|
|
6290
6416
|
let accounts;
|
|
6291
6417
|
try {
|
|
6292
|
-
accounts = await listCodexAccountStatuses2(db, input.workspaceId);
|
|
6418
|
+
accounts = await listCodexAccountStatuses2(db, input.workspaceId, attempt.turnId);
|
|
6293
6419
|
} catch (metadataError) {
|
|
6294
6420
|
const recoveryFailure = postClaimDatabaseRecoveryFailure({
|
|
6295
6421
|
error: metadataError,
|
|
@@ -6476,6 +6602,11 @@ async function settleTurnFailure(deps) {
|
|
|
6476
6602
|
{ onArmed: () => leases.codex.held = false }
|
|
6477
6603
|
);
|
|
6478
6604
|
control.activityError = error51;
|
|
6605
|
+
if (evaluated.action === "stopped") {
|
|
6606
|
+
control.activityStatus = evaluated.sessionStatus === "queued" ? "idle" : "failed";
|
|
6607
|
+
control.turnMetricOutcome = "failed";
|
|
6608
|
+
return claimedResult({ status: control.activityStatus });
|
|
6609
|
+
}
|
|
6479
6610
|
if (evaluated.action === "resumed") {
|
|
6480
6611
|
control.activityStatus = "recovering";
|
|
6481
6612
|
control.turnMetricOutcome = "recovering";
|
|
@@ -6725,30 +6856,6 @@ async function settleTurnFailure(deps) {
|
|
|
6725
6856
|
let failure = agentRunFailurePayload(error51, {
|
|
6726
6857
|
isCodexTurn: billingState.isCodexTurn
|
|
6727
6858
|
});
|
|
6728
|
-
if (isSessionEventPersistenceError2(error51)) {
|
|
6729
|
-
observability.error("session event persistence failed", {
|
|
6730
|
-
accountId: input.accountId,
|
|
6731
|
-
workspaceId: input.workspaceId,
|
|
6732
|
-
sessionId: input.sessionId,
|
|
6733
|
-
turnId: attempt.turnId,
|
|
6734
|
-
attemptId: input.attemptId,
|
|
6735
|
-
code: error51.details.code,
|
|
6736
|
-
sqlState: error51.details.sqlState ?? "unknown",
|
|
6737
|
-
stage: error51.details.stage,
|
|
6738
|
-
eventTypes: error51.details.eventTypes.join(","),
|
|
6739
|
-
correlationId: error51.details.correlationId,
|
|
6740
|
-
attempts: error51.details.attempts,
|
|
6741
|
-
retryOutcome: error51.details.retryOutcome,
|
|
6742
|
-
dbSeverity: error51.details.database.severity,
|
|
6743
|
-
dbSchema: error51.details.database.schema,
|
|
6744
|
-
dbTable: error51.details.database.table,
|
|
6745
|
-
dbColumn: error51.details.database.column,
|
|
6746
|
-
dbDataType: error51.details.database.dataType,
|
|
6747
|
-
dbConstraint: error51.details.database.constraint,
|
|
6748
|
-
dbRoutine: error51.details.database.routine,
|
|
6749
|
-
error: error51.message
|
|
6750
|
-
});
|
|
6751
|
-
}
|
|
6752
6859
|
if (failure.retryable && eventing.publish && attempt.turnId && eventing.turnStartedPublished) {
|
|
6753
6860
|
const nextProviderRecoveryCount = attempt.providerRecoveryCount + 1;
|
|
6754
6861
|
const recoveryResult = providerRecoveryResult({
|
|
@@ -6892,12 +6999,14 @@ import {
|
|
|
6892
6999
|
interruptionKindForCallItem,
|
|
6893
7000
|
releaseMcpResultCustomDataFromSdkEvent,
|
|
6894
7001
|
findCompactionNeededError,
|
|
7002
|
+
compactionProviderRejection,
|
|
6895
7003
|
withRunCredentialsSession,
|
|
6896
7004
|
runOwnedSandboxSetup
|
|
6897
7005
|
} from "@opengeni/runtime";
|
|
6898
7006
|
import { serviceTierForLatencyMode } from "@opengeni/config";
|
|
6899
7007
|
|
|
6900
7008
|
// src/activities/context-compaction.ts
|
|
7009
|
+
import { readReasoningConfiguration } from "@opengeni/codex";
|
|
6901
7010
|
import {
|
|
6902
7011
|
applyContextCompaction,
|
|
6903
7012
|
getActiveSessionHistoryItemsPaged as getActiveSessionHistoryItemsPaged2,
|
|
@@ -7059,7 +7168,8 @@ async function settleSkippedAfterStart(db, scope, options, reason) {
|
|
|
7059
7168
|
// After `compaction.started`, always settle the landmark. Do not require
|
|
7060
7169
|
// an operator `/compact` flag — auto/overflow never set one.
|
|
7061
7170
|
requirePendingRequest: false,
|
|
7062
|
-
clearRequestedCompaction
|
|
7171
|
+
clearRequestedCompaction,
|
|
7172
|
+
...options.providerRejection ? { providerRejection: options.providerRejection } : {}
|
|
7063
7173
|
});
|
|
7064
7174
|
if (!skipped.recorded) {
|
|
7065
7175
|
throw new TurnAttemptFencedError(
|
|
@@ -7102,7 +7212,8 @@ async function compactContextRemoteV2(db, settings, scope, canonicalItems, items
|
|
|
7102
7212
|
);
|
|
7103
7213
|
const estimatedTokensAfter = estimateTokens(await projectForWire(replacementHistory));
|
|
7104
7214
|
const replacementFingerprint = compactionReplacementFingerprint(replacementHistory);
|
|
7105
|
-
const
|
|
7215
|
+
const summaryIndex = replacementHistory.length - (readReasoningConfiguration(replacementHistory.at(-1) ?? {}) ? 2 : 1);
|
|
7216
|
+
const tailItem = replacementHistory[summaryIndex];
|
|
7106
7217
|
if (!tailItem) {
|
|
7107
7218
|
throw new EmptyCompactionSummaryError({
|
|
7108
7219
|
stage: "remote_v2_replacement",
|
|
@@ -7116,7 +7227,8 @@ async function compactContextRemoteV2(db, settings, scope, canonicalItems, items
|
|
|
7116
7227
|
turnId: scope.turnId,
|
|
7117
7228
|
expectedExecutionGeneration: scope.executionGeneration,
|
|
7118
7229
|
expectedAttemptId: scope.attemptId,
|
|
7119
|
-
replacementItems: replacementHistory.slice(0,
|
|
7230
|
+
replacementItems: replacementHistory.slice(0, summaryIndex),
|
|
7231
|
+
...replacementHistory.length > summaryIndex + 1 ? { trailingItems: replacementHistory.slice(summaryIndex + 1) } : {},
|
|
7120
7232
|
summaryItem: tailItem,
|
|
7121
7233
|
...options.clearRequestedCompaction ? { clearRequestedCompaction: true } : {},
|
|
7122
7234
|
eventPayload: {
|
|
@@ -7158,7 +7270,8 @@ async function compactContextPortable(db, settings, scope, canonicalItems, items
|
|
|
7158
7270
|
const estimatedTokensAfter = estimateTokens(await projectForWire(replacementHistory));
|
|
7159
7271
|
const replacementFingerprint = compactionReplacementFingerprint(replacementHistory);
|
|
7160
7272
|
const previousReplacementFingerprint = latestCompactionReplacementFingerprint(canonicalItems);
|
|
7161
|
-
const
|
|
7273
|
+
const summaryIndex = replacementHistory.length - (readReasoningConfiguration(replacementHistory.at(-1) ?? {}) ? 2 : 1);
|
|
7274
|
+
const summaryItem = replacementHistory[summaryIndex];
|
|
7162
7275
|
if (!summaryItem) {
|
|
7163
7276
|
return await settleSkippedAfterStart(db, scope, options, "summarization_failed");
|
|
7164
7277
|
}
|
|
@@ -7175,7 +7288,8 @@ async function compactContextPortable(db, settings, scope, canonicalItems, items
|
|
|
7175
7288
|
turnId: scope.turnId,
|
|
7176
7289
|
expectedExecutionGeneration: scope.executionGeneration,
|
|
7177
7290
|
expectedAttemptId: scope.attemptId,
|
|
7178
|
-
replacementItems: replacementHistory.slice(0,
|
|
7291
|
+
replacementItems: replacementHistory.slice(0, summaryIndex),
|
|
7292
|
+
...replacementHistory.length > summaryIndex + 1 ? { trailingItems: replacementHistory.slice(summaryIndex + 1) } : {},
|
|
7179
7293
|
summaryItem,
|
|
7180
7294
|
...options.clearRequestedCompaction ? { clearRequestedCompaction: true } : {},
|
|
7181
7295
|
eventPayload: {
|
|
@@ -7263,6 +7377,24 @@ async function retentionTokenCounts(items, project2) {
|
|
|
7263
7377
|
return counts;
|
|
7264
7378
|
}
|
|
7265
7379
|
|
|
7380
|
+
// src/activities/agent-turn/turn-sandbox-access.ts
|
|
7381
|
+
function ownedTurnSandboxForAgent(sandboxState) {
|
|
7382
|
+
return sandboxState.lazyOwnedSandbox ?? sandboxState.resolvedSandbox?.established;
|
|
7383
|
+
}
|
|
7384
|
+
async function resolveTurnSandboxAccess(sandboxState, sdkOwnedSandboxSession, unavailableMessage) {
|
|
7385
|
+
let sandbox = sandboxState.resolvedSandbox;
|
|
7386
|
+
if (!sandbox && sandboxState.turnSandboxProvisioner) {
|
|
7387
|
+
sandbox = await sandboxState.turnSandboxProvisioner.get();
|
|
7388
|
+
}
|
|
7389
|
+
const session = ownedTurnSandboxForAgent(sandboxState)?.session ?? sandbox?.established.session ?? sdkOwnedSandboxSession;
|
|
7390
|
+
if (!session) throw new Error(unavailableMessage);
|
|
7391
|
+
return {
|
|
7392
|
+
sandbox,
|
|
7393
|
+
session,
|
|
7394
|
+
leaseEpoch: sandbox?.leaseEpoch ?? 0
|
|
7395
|
+
};
|
|
7396
|
+
}
|
|
7397
|
+
|
|
7266
7398
|
// src/activities/open-suffix-resume.ts
|
|
7267
7399
|
import {
|
|
7268
7400
|
OPEN_SUFFIX_RUN_STATE_BLOB,
|
|
@@ -7577,7 +7709,7 @@ import {
|
|
|
7577
7709
|
import { hasPermission } from "@opengeni/core";
|
|
7578
7710
|
import {
|
|
7579
7711
|
AUTOMATIC_SESSION_TITLE_FALLBACK,
|
|
7580
|
-
DEFAULT_FIRST_PARTY_MCP_PERMISSIONS
|
|
7712
|
+
DEFAULT_FIRST_PARTY_MCP_PERMISSIONS
|
|
7581
7713
|
} from "@opengeni/contracts";
|
|
7582
7714
|
var SESSION_TITLE_MODEL_TOOL_NAME = "opengeni__set_session_title";
|
|
7583
7715
|
var SESSION_TITLE_DESCRIPTION = "Set this session's display title to a concise 3-7 word topic label. Use a stable noun phrase about the actual task or subject, never a quote/prefix of a prompt, greeting, request boilerplate, URL, identifier, credential, token, or other sensitive value. Call once on a new session, then only when the topic materially changes. Never call it as routine setup after a continuation, resume, or interruption, or merely to reassert the same title. A human-set title cannot be replaced.";
|
|
@@ -7586,7 +7718,7 @@ function shouldRequestMissingSessionTitle(input) {
|
|
|
7586
7718
|
const needsSemanticTitle = input.titleSource !== "user" && (!title || title === AUTOMATIC_SESSION_TITLE_FALLBACK);
|
|
7587
7719
|
if (!needsSemanticTitle) return false;
|
|
7588
7720
|
if (!input.firstPartyMcpTools.includes("set_session_title")) return false;
|
|
7589
|
-
const permissions = input.firstPartyMcpPermissions ??
|
|
7721
|
+
const permissions = input.firstPartyMcpPermissions ?? DEFAULT_FIRST_PARTY_MCP_PERMISSIONS;
|
|
7590
7722
|
return hasPermission([...permissions], "sessions:control");
|
|
7591
7723
|
}
|
|
7592
7724
|
function sessionTitleToolPlan(input) {
|
|
@@ -8171,7 +8303,7 @@ async function runTurnStreamAttempt(deps) {
|
|
|
8171
8303
|
});
|
|
8172
8304
|
}
|
|
8173
8305
|
};
|
|
8174
|
-
const ownedEstablished = sandboxState
|
|
8306
|
+
const ownedEstablished = ownedTurnSandboxForAgent(sandboxState);
|
|
8175
8307
|
const runStreamOnce = async () => {
|
|
8176
8308
|
const eagerResolvedSandbox = sandboxState.resolvedSandbox;
|
|
8177
8309
|
if (eagerResolvedSandbox && !sandboxState.lazyOwnedSandbox && ownedEstablished) {
|
|
@@ -8254,8 +8386,8 @@ async function runTurnStreamAttempt(deps) {
|
|
|
8254
8386
|
eventing.firstModelRequestPreparationStartedAt = performance.now();
|
|
8255
8387
|
eventing.firstModelRequestCheckpointAt = eventing.firstModelRequestPreparationStartedAt;
|
|
8256
8388
|
}
|
|
8257
|
-
const
|
|
8258
|
-
let
|
|
8389
|
+
const streamInitializationStartedAt = performance.now();
|
|
8390
|
+
let streamInitializationOutcome = "completed";
|
|
8259
8391
|
try {
|
|
8260
8392
|
if (!workerPreparationTotalRecorded) {
|
|
8261
8393
|
workerPreparationTotalRecorded = true;
|
|
@@ -8354,15 +8486,15 @@ async function runTurnStreamAttempt(deps) {
|
|
|
8354
8486
|
} : {}
|
|
8355
8487
|
});
|
|
8356
8488
|
} catch (error51) {
|
|
8357
|
-
|
|
8489
|
+
streamInitializationOutcome = "failed";
|
|
8358
8490
|
throw error51;
|
|
8359
8491
|
} finally {
|
|
8360
8492
|
recordTurnStartupPhase(observability, {
|
|
8361
|
-
phase: "
|
|
8493
|
+
phase: "runtime_stream_initialization",
|
|
8362
8494
|
provider: turnExecutionPolicy.providerId,
|
|
8363
8495
|
backend: activeSandboxBackend ?? groupBoxBackend,
|
|
8364
|
-
outcome:
|
|
8365
|
-
durationSeconds: (performance.now() -
|
|
8496
|
+
outcome: streamInitializationOutcome,
|
|
8497
|
+
durationSeconds: (performance.now() - streamInitializationStartedAt) / 1e3
|
|
8366
8498
|
});
|
|
8367
8499
|
}
|
|
8368
8500
|
};
|
|
@@ -9070,7 +9202,7 @@ async function runTurnStreamAttempt(deps) {
|
|
|
9070
9202
|
})) {
|
|
9071
9203
|
return claimedResult({ status: "cancelled" });
|
|
9072
9204
|
}
|
|
9073
|
-
if (generateSessionTitleInParallel && runtime.generateSessionTitle && !runtimeCancellationSignal.aborted) {
|
|
9205
|
+
if (turn.source !== "compaction" && generateSessionTitleInParallel && runtime.generateSessionTitle && !runtimeCancellationSignal.aborted) {
|
|
9074
9206
|
const serviceTier = serviceTierForLatencyMode(
|
|
9075
9207
|
turnExecutionPolicy.providerId,
|
|
9076
9208
|
turnExecutionPolicy.latencyMode
|
|
@@ -9133,6 +9265,7 @@ async function runTurnStreamAttempt(deps) {
|
|
|
9133
9265
|
let compacted = false;
|
|
9134
9266
|
let compactionHandled = false;
|
|
9135
9267
|
let compactionFailureMessage = null;
|
|
9268
|
+
let compactionFailureError = null;
|
|
9136
9269
|
let compactionRequestCleared = false;
|
|
9137
9270
|
try {
|
|
9138
9271
|
const outcome = await forceContextCompaction(
|
|
@@ -9163,7 +9296,8 @@ async function runTurnStreamAttempt(deps) {
|
|
|
9163
9296
|
},
|
|
9164
9297
|
{
|
|
9165
9298
|
clearRequestedCompaction: recoveryKind === "operator",
|
|
9166
|
-
publishLiveEvents: publishCompactionLiveEvents
|
|
9299
|
+
publishLiveEvents: publishCompactionLiveEvents,
|
|
9300
|
+
providerRejection: compactionProviderRejection(compactError)
|
|
9167
9301
|
}
|
|
9168
9302
|
);
|
|
9169
9303
|
compactionRequestCleared = landmark.requestConsumed;
|
|
@@ -9171,6 +9305,7 @@ async function runTurnStreamAttempt(deps) {
|
|
|
9171
9305
|
await finishParallelSessionTitle();
|
|
9172
9306
|
const deferredSteer2 = await settleDeferredSteerAfterCompaction();
|
|
9173
9307
|
if (deferredSteer2) return deferredSteer2;
|
|
9308
|
+
compactionFailureError = compactError;
|
|
9174
9309
|
compactionFailureMessage = String(compactionFailureReasonFromError(compactError));
|
|
9175
9310
|
observability.warn("context compaction recovery compaction failed", {
|
|
9176
9311
|
sessionId: input.sessionId,
|
|
@@ -9185,13 +9320,9 @@ async function runTurnStreamAttempt(deps) {
|
|
|
9185
9320
|
events: [
|
|
9186
9321
|
{
|
|
9187
9322
|
type: "turn.failed",
|
|
9188
|
-
payload: {
|
|
9189
|
-
error: errorMessage
|
|
9190
|
-
|
|
9191
|
-
retryable: false,
|
|
9192
|
-
recovery: "user_message",
|
|
9193
|
-
compacted: false
|
|
9194
|
-
}
|
|
9323
|
+
payload: compactionFailureTurnEventPayload(compactionFailureError, {
|
|
9324
|
+
error: errorMessage
|
|
9325
|
+
})
|
|
9195
9326
|
},
|
|
9196
9327
|
{
|
|
9197
9328
|
type: "session.status.changed",
|
|
@@ -9213,6 +9344,27 @@ async function runTurnStreamAttempt(deps) {
|
|
|
9213
9344
|
await finishParallelSessionTitle();
|
|
9214
9345
|
const deferredSteer = await settleDeferredSteerAfterCompaction();
|
|
9215
9346
|
if (deferredSteer) return deferredSteer;
|
|
9347
|
+
if (turn.source === "compaction") {
|
|
9348
|
+
const settled = await eventing.settle({
|
|
9349
|
+
events: [
|
|
9350
|
+
{
|
|
9351
|
+
type: "turn.completed",
|
|
9352
|
+
payload: {
|
|
9353
|
+
maintenance: "context_compaction",
|
|
9354
|
+
result: compacted ? "compacted" : "already_applied"
|
|
9355
|
+
}
|
|
9356
|
+
},
|
|
9357
|
+
{ type: "session.status.changed", payload: { status: "idle" } }
|
|
9358
|
+
],
|
|
9359
|
+
turnStatus: "completed",
|
|
9360
|
+
sessionStatus: "idle",
|
|
9361
|
+
activeTurnId: null
|
|
9362
|
+
});
|
|
9363
|
+
if (!settled) return claimedResult({ status: "cancelled" });
|
|
9364
|
+
control.turnMetricOutcome = "completed";
|
|
9365
|
+
control.activityStatus = "idle";
|
|
9366
|
+
return claimedResult({ status: "idle" });
|
|
9367
|
+
}
|
|
9216
9368
|
retriedAfterCompaction = true;
|
|
9217
9369
|
observability.info("context compaction recovery retrying turn after compaction", {
|
|
9218
9370
|
sessionId: input.sessionId,
|
|
@@ -9228,6 +9380,18 @@ async function runTurnStreamAttempt(deps) {
|
|
|
9228
9380
|
}
|
|
9229
9381
|
}
|
|
9230
9382
|
|
|
9383
|
+
// src/activities/agent-turn/recovery-warning.ts
|
|
9384
|
+
import { getSandboxRecoveryDiscontinuity } from "@opengeni/db";
|
|
9385
|
+
var FILESYSTEM_DISCONTINUITY_PROTOCOL = 1;
|
|
9386
|
+
async function recoveryAwareSessionInstructions(db, workspaceId, session) {
|
|
9387
|
+
const filesystemDiscontinuity = await getSandboxRecoveryDiscontinuity(
|
|
9388
|
+
db,
|
|
9389
|
+
workspaceId,
|
|
9390
|
+
session.id
|
|
9391
|
+
);
|
|
9392
|
+
return [session.instructions, filesystemDiscontinuity].filter(Boolean).join("\n\n");
|
|
9393
|
+
}
|
|
9394
|
+
|
|
9231
9395
|
// src/activities/agent-turn/claim.ts
|
|
9232
9396
|
import {
|
|
9233
9397
|
applySessionTurnSettlement,
|
|
@@ -9240,6 +9404,7 @@ import {
|
|
|
9240
9404
|
requireSession
|
|
9241
9405
|
} from "@opengeni/db";
|
|
9242
9406
|
import { appendAndPublishTurnEventsFenced as appendAndPublishTurnEventsFenced2, publishDurableSessionEvents as publishDurableSessionEvents4 } from "@opengeni/events";
|
|
9407
|
+
import { linkCurrentSpanToAdmission, turnExecutionTelemetryKey } from "@opengeni/observability";
|
|
9243
9408
|
import {
|
|
9244
9409
|
assertTurnExecutionPolicyMatchesConfigV1,
|
|
9245
9410
|
resolveTurnExecutionPolicyV1 as resolveTurnExecutionPolicyV12
|
|
@@ -9269,6 +9434,7 @@ import {
|
|
|
9269
9434
|
getWorkspaceOpenRouterCustomModelForExecution,
|
|
9270
9435
|
listSessionMcpServerMetadata,
|
|
9271
9436
|
listSessionMcpServersForRun,
|
|
9437
|
+
getSessionAttemptMcpApprovalPolicies,
|
|
9272
9438
|
listWorkspaceGatewayCustomModels,
|
|
9273
9439
|
listWorkspaceOpenRouterCustomModels,
|
|
9274
9440
|
workspaceCodexSubscriptionActive,
|
|
@@ -9280,10 +9446,22 @@ import {
|
|
|
9280
9446
|
} from "@opengeni/db";
|
|
9281
9447
|
async function settingsWithSessionMcpServersForRun(db, workspaceId, sessionId, attemptId, settings, options) {
|
|
9282
9448
|
const encryptionKey = environmentsEncryptionKeyBytes(settings);
|
|
9449
|
+
const policies = await getSessionAttemptMcpApprovalPolicies(
|
|
9450
|
+
db,
|
|
9451
|
+
workspaceId,
|
|
9452
|
+
sessionId,
|
|
9453
|
+
attemptId
|
|
9454
|
+
);
|
|
9455
|
+
const policySettings = {
|
|
9456
|
+
...settings,
|
|
9457
|
+
mcpServers: settings.mcpServers.map(
|
|
9458
|
+
(server) => Object.hasOwn(policies, server.id) ? { ...server, requireApproval: policies[server.id] } : server
|
|
9459
|
+
)
|
|
9460
|
+
};
|
|
9283
9461
|
if (!encryptionKey) {
|
|
9284
9462
|
const metadata = await listSessionMcpServerMetadata(db, workspaceId, sessionId);
|
|
9285
9463
|
if (metadata.length === 0) {
|
|
9286
|
-
return
|
|
9464
|
+
return policySettings;
|
|
9287
9465
|
}
|
|
9288
9466
|
if (metadata.some((server) => server.headerNames.length > 0)) {
|
|
9289
9467
|
throw new Error(
|
|
@@ -9299,7 +9477,7 @@ async function settingsWithSessionMcpServersForRun(db, workspaceId, sessionId, a
|
|
|
9299
9477
|
encryptionKey ?? null
|
|
9300
9478
|
);
|
|
9301
9479
|
options?.onResolvedServers?.(servers);
|
|
9302
|
-
return settingsWithSessionMcpServers(
|
|
9480
|
+
return settingsWithSessionMcpServers(policySettings, servers);
|
|
9303
9481
|
}
|
|
9304
9482
|
function settingsWithSessionMcpServers(settings, servers) {
|
|
9305
9483
|
if (servers.length === 0) {
|
|
@@ -9484,6 +9662,7 @@ async function claimTurnAttempt(deps) {
|
|
|
9484
9662
|
update
|
|
9485
9663
|
});
|
|
9486
9664
|
const claim = await claimSessionWorkForAttempt(db, input.workspaceId, {
|
|
9665
|
+
filesystemDiscontinuityProtocol: FILESYSTEM_DISCONTINUITY_PROTOCOL,
|
|
9487
9666
|
sessionId: input.sessionId,
|
|
9488
9667
|
workflowId: input.workflowId,
|
|
9489
9668
|
workflowRunId: input.workflowRunId,
|
|
@@ -9527,7 +9706,8 @@ async function claimTurnAttempt(deps) {
|
|
|
9527
9706
|
const codexSubscriptionActive = await workspaceCodexSubscriptionActive2(
|
|
9528
9707
|
db,
|
|
9529
9708
|
mcpSettings,
|
|
9530
|
-
input.workspaceId
|
|
9709
|
+
input.workspaceId,
|
|
9710
|
+
turn.id
|
|
9531
9711
|
);
|
|
9532
9712
|
const codexSettings = await settingsWithCodexCredential(
|
|
9533
9713
|
db,
|
|
@@ -9593,6 +9773,7 @@ async function claimTurnAttempt(deps) {
|
|
|
9593
9773
|
if (!trigger) {
|
|
9594
9774
|
throw new Error(`Trigger event not found: ${attempt.triggerEventId}`);
|
|
9595
9775
|
}
|
|
9776
|
+
if (trigger.type === "user.message") linkCurrentSpanToAdmission(trigger.id);
|
|
9596
9777
|
const humanInputResume = await getHumanInputResumeForEvent2(
|
|
9597
9778
|
db,
|
|
9598
9779
|
input.workspaceId,
|
|
@@ -9608,6 +9789,7 @@ async function claimTurnAttempt(deps) {
|
|
|
9608
9789
|
attempt.triggerType = trigger.type;
|
|
9609
9790
|
const attachPendingUpdatesAfterOpenSuffix = async () => {
|
|
9610
9791
|
const attached = await claimSessionWorkForAttempt(db, input.workspaceId, {
|
|
9792
|
+
filesystemDiscontinuityProtocol: FILESYSTEM_DISCONTINUITY_PROTOCOL,
|
|
9611
9793
|
sessionId: input.sessionId,
|
|
9612
9794
|
workflowId: input.workflowId,
|
|
9613
9795
|
workflowRunId: input.workflowRunId,
|
|
@@ -9647,6 +9829,7 @@ async function claimTurnAttempt(deps) {
|
|
|
9647
9829
|
turnId: attempt.turnId,
|
|
9648
9830
|
opAcks: {}
|
|
9649
9831
|
};
|
|
9832
|
+
eventing.heartbeatDetails = heartbeatDetails;
|
|
9650
9833
|
const opJournal = makeTurnOpJournal(activityContext, heartbeatDetails);
|
|
9651
9834
|
eventing.heartbeatTimer = startActivityHeartbeat(activityContext, heartbeatDetails);
|
|
9652
9835
|
let producerSeq = 0;
|
|
@@ -9773,6 +9956,11 @@ async function claimTurnAttempt(deps) {
|
|
|
9773
9956
|
throwIfTurnCancelled();
|
|
9774
9957
|
recordTurnStartupPhase(observability, {
|
|
9775
9958
|
phase: "claim_and_policy",
|
|
9959
|
+
executionCorrelationId: turnExecutionTelemetryKey(
|
|
9960
|
+
input.workspaceId,
|
|
9961
|
+
input.sessionId,
|
|
9962
|
+
input.attemptId
|
|
9963
|
+
),
|
|
9776
9964
|
provider: turnExecutionPolicy.providerId,
|
|
9777
9965
|
backend: turn.sandboxBackend,
|
|
9778
9966
|
outcome: "completed",
|
|
@@ -10105,10 +10293,17 @@ async function selectCodexTurnCapacity(deps) {
|
|
|
10105
10293
|
selectForTurn
|
|
10106
10294
|
);
|
|
10107
10295
|
if (leased.decision.kind === "allCapped") {
|
|
10108
|
-
await refreshCappedCodexUsageRows(
|
|
10109
|
-
|
|
10110
|
-
|
|
10111
|
-
|
|
10296
|
+
await refreshCappedCodexUsageRows(
|
|
10297
|
+
db,
|
|
10298
|
+
settings,
|
|
10299
|
+
input.workspaceId,
|
|
10300
|
+
leased.accounts,
|
|
10301
|
+
{
|
|
10302
|
+
signalCodexCapacityWorkflow,
|
|
10303
|
+
wakeSessionWorkflow
|
|
10304
|
+
},
|
|
10305
|
+
turn.id
|
|
10306
|
+
);
|
|
10112
10307
|
leaseAcquisitionStartedAtMs = performance.now();
|
|
10113
10308
|
leased = await acquireCodexCredentialLease(
|
|
10114
10309
|
db,
|
|
@@ -10348,6 +10543,11 @@ async function selectCodexTurnCapacity(deps) {
|
|
|
10348
10543
|
}
|
|
10349
10544
|
}
|
|
10350
10545
|
);
|
|
10546
|
+
if (evaluated.action === "stopped") {
|
|
10547
|
+
control.turnMetricOutcome = "failed";
|
|
10548
|
+
control.activityStatus = evaluated.sessionStatus === "queued" ? "idle" : "failed";
|
|
10549
|
+
return { exit: claimedResult({ status: control.activityStatus }) };
|
|
10550
|
+
}
|
|
10351
10551
|
if (evaluated.action === "resumed") {
|
|
10352
10552
|
control.turnMetricOutcome = "recovering";
|
|
10353
10553
|
control.activityStatus = "recovering";
|
|
@@ -10442,6 +10642,11 @@ async function selectCodexTurnCapacity(deps) {
|
|
|
10442
10642
|
}
|
|
10443
10643
|
}
|
|
10444
10644
|
);
|
|
10645
|
+
if (evaluated.action === "stopped") {
|
|
10646
|
+
control.turnMetricOutcome = "failed";
|
|
10647
|
+
control.activityStatus = evaluated.sessionStatus === "queued" ? "idle" : "failed";
|
|
10648
|
+
return { exit: claimedResult({ status: control.activityStatus }) };
|
|
10649
|
+
}
|
|
10445
10650
|
if (evaluated.action === "resumed") {
|
|
10446
10651
|
control.turnMetricOutcome = "recovering";
|
|
10447
10652
|
control.activityStatus = "recovering";
|
|
@@ -10525,6 +10730,11 @@ async function selectCodexTurnCapacity(deps) {
|
|
|
10525
10730
|
failurePayload
|
|
10526
10731
|
}
|
|
10527
10732
|
);
|
|
10733
|
+
if (evaluated.action === "stopped") {
|
|
10734
|
+
control.turnMetricOutcome = "failed";
|
|
10735
|
+
control.activityStatus = evaluated.sessionStatus === "queued" ? "idle" : "failed";
|
|
10736
|
+
return { exit: claimedResult({ status: control.activityStatus }) };
|
|
10737
|
+
}
|
|
10528
10738
|
if (evaluated.action === "resumed") {
|
|
10529
10739
|
control.turnMetricOutcome = "recovering";
|
|
10530
10740
|
control.activityStatus = "recovering";
|
|
@@ -10653,6 +10863,7 @@ import {
|
|
|
10653
10863
|
renderWorkspaceGovernanceContext
|
|
10654
10864
|
} from "@opengeni/runtime";
|
|
10655
10865
|
import { settingsWithResolvedModelContext } from "@opengeni/config";
|
|
10866
|
+
import { projectReasoningConfigurations, supportsReasoningConfiguration } from "@opengeni/codex";
|
|
10656
10867
|
import { resolveRigProviderImageForRun } from "@opengeni/core";
|
|
10657
10868
|
import { retryWhileMissing as retryWhileMissing3 } from "@opengeni/storage";
|
|
10658
10869
|
import { WorkspaceModelPolicyBlockedError } from "@opengeni/runtime";
|
|
@@ -11002,12 +11213,10 @@ async function prepareGovernanceAndModel(deps) {
|
|
|
11002
11213
|
executionGeneration: turn.executionGeneration
|
|
11003
11214
|
};
|
|
11004
11215
|
const [
|
|
11005
|
-
packRuntime,
|
|
11006
11216
|
rigMaterialization,
|
|
11007
11217
|
[workspace, companyProfileSnapshot, instructionPolicySnapshot, preferenceSnapshot],
|
|
11008
11218
|
workspaceModelPolicy
|
|
11009
11219
|
] = await Promise.all([
|
|
11010
|
-
resolveWorkspacePackRuntime(db, input.workspaceId),
|
|
11011
11220
|
session.rigId && session.rigVersionId ? (async () => await materializeRigVersionForAttempt(db, {
|
|
11012
11221
|
accountId: input.accountId,
|
|
11013
11222
|
workspaceId: input.workspaceId,
|
|
@@ -11073,11 +11282,7 @@ async function prepareGovernanceAndModel(deps) {
|
|
|
11073
11282
|
);
|
|
11074
11283
|
} catch {
|
|
11075
11284
|
}
|
|
11076
|
-
const logicalSandboxSettings =
|
|
11077
|
-
capabilitySettings,
|
|
11078
|
-
packRuntime.sandboxImage,
|
|
11079
|
-
packRuntime.sandboxProviderImages
|
|
11080
|
-
);
|
|
11285
|
+
const logicalSandboxSettings = capabilitySettings;
|
|
11081
11286
|
const providerImageSelection = await resolveRigProviderImageForRun(
|
|
11082
11287
|
logicalSandboxSettings,
|
|
11083
11288
|
rigVersion,
|
|
@@ -11086,9 +11291,8 @@ async function prepareGovernanceAndModel(deps) {
|
|
|
11086
11291
|
const providerImageSettings = providerImageSelection.settings;
|
|
11087
11292
|
const verifiedRigProviderImageId = providerImageSelection.reason === "selected" ? providerImageSelection.imageId ?? void 0 : void 0;
|
|
11088
11293
|
const baseRunSettings = {
|
|
11089
|
-
//
|
|
11090
|
-
//
|
|
11091
|
-
// provider-native ID is then applied only to fresh creation without
|
|
11294
|
+
// A Rig uses the deployment platform base. A matching verified
|
|
11295
|
+
// provider-native ID is applied only to fresh creation without
|
|
11092
11296
|
// changing the logical lease image.
|
|
11093
11297
|
...providerImageSettings,
|
|
11094
11298
|
openaiModel: turn.model,
|
|
@@ -11128,8 +11332,12 @@ async function prepareGovernanceAndModel(deps) {
|
|
|
11128
11332
|
fileIds
|
|
11129
11333
|
})
|
|
11130
11334
|
);
|
|
11335
|
+
const useReasoningUpdates = runSettings.reasoningConfigurationUpdatesEnabled && providerApi === "responses" && (resolvedModel?.provider.id === "codex" || resolvedModel?.provider.id === "openai") && supportsReasoningConfiguration(turnExecutionPolicy.upstreamModelId, turn.reasoningEffort);
|
|
11131
11336
|
const modelHistoryProjector = async (items, projectionOptions) => projectModelInputForCapabilities(
|
|
11132
|
-
|
|
11337
|
+
projectReasoningConfigurations(
|
|
11338
|
+
await attachmentProjector(items, projectionOptions),
|
|
11339
|
+
useReasoningUpdates
|
|
11340
|
+
),
|
|
11133
11341
|
modelInputPolicy
|
|
11134
11342
|
);
|
|
11135
11343
|
const generatedImageHistoryProjector = async (items) => {
|
|
@@ -11187,7 +11395,6 @@ async function prepareGovernanceAndModel(deps) {
|
|
|
11187
11395
|
return {
|
|
11188
11396
|
ok: {
|
|
11189
11397
|
runtimePreparationStartedAt,
|
|
11190
|
-
packRuntime,
|
|
11191
11398
|
rigVersion,
|
|
11192
11399
|
rigName,
|
|
11193
11400
|
agentHumanInputEnabled,
|
|
@@ -11221,8 +11428,11 @@ import {
|
|
|
11221
11428
|
appendWorkspaceMemory,
|
|
11222
11429
|
composeAgentInstructions,
|
|
11223
11430
|
requestRemoteCompactionV2,
|
|
11224
|
-
|
|
11225
|
-
|
|
11431
|
+
preparedCompactionRequest,
|
|
11432
|
+
queuePreparedCompaction,
|
|
11433
|
+
compactionThresholdTokens as compactionThresholdTokens2,
|
|
11434
|
+
CompactionNeededError,
|
|
11435
|
+
compactionProviderRejection as compactionProviderRejection2,
|
|
11226
11436
|
SUMMARY_BUFFER_TOKENS as SUMMARY_BUFFER_TOKENS2
|
|
11227
11437
|
} from "@opengeni/runtime";
|
|
11228
11438
|
async function prepareCompaction(deps) {
|
|
@@ -11260,9 +11470,6 @@ async function prepareCompaction(deps) {
|
|
|
11260
11470
|
withCodexRemoteCompaction
|
|
11261
11471
|
} = deps;
|
|
11262
11472
|
const remotePrefix = {
|
|
11263
|
-
tools: [],
|
|
11264
|
-
instructions: "",
|
|
11265
|
-
toolsReady: false,
|
|
11266
11473
|
agent: null
|
|
11267
11474
|
};
|
|
11268
11475
|
const promptCacheKey = acceptsPromptCacheKeyForTurn(resolvedModel) ? input.sessionId : void 0;
|
|
@@ -11315,38 +11522,16 @@ async function prepareCompaction(deps) {
|
|
|
11315
11522
|
...promptCacheKey ? { promptCacheKey } : {}
|
|
11316
11523
|
});
|
|
11317
11524
|
const remoteCompactionRequester = resolvedModel && billingState.isCodexTurn ? (s, m) => withCodexRemoteCompaction(async () => {
|
|
11318
|
-
if (!remotePrefix.
|
|
11319
|
-
|
|
11320
|
-
stage: "remote_v2_instructions",
|
|
11321
|
-
reason: "agent_missing_system_instructions"
|
|
11322
|
-
});
|
|
11323
|
-
}
|
|
11324
|
-
if (!remotePrefix.toolsReady) {
|
|
11325
|
-
if (!remotePrefix.agent) {
|
|
11326
|
-
throw new EmptyCompactionSummaryError2({
|
|
11327
|
-
stage: "remote_v2_tools",
|
|
11328
|
-
reason: "agent_missing_for_tools"
|
|
11329
|
-
});
|
|
11330
|
-
}
|
|
11331
|
-
try {
|
|
11332
|
-
remotePrefix.tools = await serializedToolsForRemoteCompaction(remotePrefix.agent);
|
|
11333
|
-
} catch (error51) {
|
|
11334
|
-
throw new EmptyCompactionSummaryError2({
|
|
11335
|
-
stage: "remote_v2_tools",
|
|
11336
|
-
reason: "serialize_tools_failed",
|
|
11337
|
-
error: String(error51)
|
|
11338
|
-
});
|
|
11339
|
-
}
|
|
11340
|
-
remotePrefix.toolsReady = true;
|
|
11341
|
-
}
|
|
11525
|
+
if (!remotePrefix.agent) throw new Error("Compaction agent is unavailable");
|
|
11526
|
+
const preparedRequest = preparedCompactionRequest(remotePrefix.agent);
|
|
11342
11527
|
return requestRemoteCompactionV2(s, m, {
|
|
11343
11528
|
client: resolvedModel.client,
|
|
11344
11529
|
provider: resolvedModel.provider,
|
|
11345
11530
|
model: turnExecutionPolicy.upstreamModelId,
|
|
11346
|
-
|
|
11347
|
-
|
|
11348
|
-
|
|
11349
|
-
|
|
11531
|
+
preparedRequest,
|
|
11532
|
+
captureAgent: remotePrefix.agent,
|
|
11533
|
+
signal: cancellationSignal,
|
|
11534
|
+
onUsage: recordCompactionUsage
|
|
11350
11535
|
});
|
|
11351
11536
|
}) : void 0;
|
|
11352
11537
|
const publishCompactionLiveEvents = async (events) => {
|
|
@@ -11458,22 +11643,16 @@ async function prepareCompaction(deps) {
|
|
|
11458
11643
|
},
|
|
11459
11644
|
{
|
|
11460
11645
|
clearRequestedCompaction: true,
|
|
11461
|
-
publishLiveEvents: publishCompactionLiveEvents
|
|
11646
|
+
publishLiveEvents: publishCompactionLiveEvents,
|
|
11647
|
+
providerRejection: compactionProviderRejection2(error51)
|
|
11462
11648
|
}
|
|
11463
11649
|
);
|
|
11464
11650
|
if (!isCompactionSummaryFailure(error51)) throw error51;
|
|
11465
|
-
const errorMessage = String(compactionFailureReasonFromError(error51));
|
|
11466
11651
|
if (!await eventing.settle({
|
|
11467
11652
|
events: [
|
|
11468
11653
|
{
|
|
11469
11654
|
type: "turn.failed",
|
|
11470
|
-
payload:
|
|
11471
|
-
error: errorMessage,
|
|
11472
|
-
code: "context_compaction_failed",
|
|
11473
|
-
retryable: false,
|
|
11474
|
-
recovery: "user_message",
|
|
11475
|
-
compacted: false
|
|
11476
|
-
}
|
|
11655
|
+
payload: compactionFailureTurnEventPayload(error51)
|
|
11477
11656
|
},
|
|
11478
11657
|
{
|
|
11479
11658
|
type: "session.status.changed",
|
|
@@ -11563,12 +11742,23 @@ async function runPostAgentCompaction(deps) {
|
|
|
11563
11742
|
agentInstructions.trim() ? agentInstructions : void 0
|
|
11564
11743
|
);
|
|
11565
11744
|
if (remoteCompactionRequester) {
|
|
11566
|
-
remotePrefix.instructions = agentInstructions;
|
|
11567
11745
|
remotePrefix.agent = agent;
|
|
11568
11746
|
}
|
|
11569
11747
|
if (compactionOnlyTurn) {
|
|
11570
11748
|
const requested = await isSessionCompactionRequested2(db, input.workspaceId, input.sessionId);
|
|
11571
11749
|
let outcome = null;
|
|
11750
|
+
if (requested && remoteCompactionRequester && session.codexCompactionMode === "remote_v2") {
|
|
11751
|
+
queuePreparedCompaction(
|
|
11752
|
+
agent,
|
|
11753
|
+
new CompactionNeededError({
|
|
11754
|
+
trigger: "operator",
|
|
11755
|
+
signalSource: "operator",
|
|
11756
|
+
signalTokens: session.lastInputTokens ?? 0,
|
|
11757
|
+
thresholdTokens: compactionThresholdTokens2(eventing.modelRunSettings)
|
|
11758
|
+
})
|
|
11759
|
+
);
|
|
11760
|
+
return { ok: { compactSummarizer } };
|
|
11761
|
+
}
|
|
11572
11762
|
if (requested) {
|
|
11573
11763
|
try {
|
|
11574
11764
|
outcome = await waitForTurnOperation(
|
|
@@ -11611,22 +11801,16 @@ async function runPostAgentCompaction(deps) {
|
|
|
11611
11801
|
},
|
|
11612
11802
|
{
|
|
11613
11803
|
clearRequestedCompaction: true,
|
|
11614
|
-
publishLiveEvents: publishCompactionLiveEvents
|
|
11804
|
+
publishLiveEvents: publishCompactionLiveEvents,
|
|
11805
|
+
providerRejection: compactionProviderRejection2(error51)
|
|
11615
11806
|
}
|
|
11616
11807
|
);
|
|
11617
11808
|
if (!isCompactionSummaryFailure(error51)) throw error51;
|
|
11618
|
-
const errorMessage = String(compactionFailureReasonFromError(error51));
|
|
11619
11809
|
if (!await eventing.settle({
|
|
11620
11810
|
events: [
|
|
11621
11811
|
{
|
|
11622
11812
|
type: "turn.failed",
|
|
11623
|
-
payload:
|
|
11624
|
-
error: errorMessage,
|
|
11625
|
-
code: "context_compaction_failed",
|
|
11626
|
-
retryable: false,
|
|
11627
|
-
recovery: "user_message",
|
|
11628
|
-
compacted: false
|
|
11629
|
-
}
|
|
11813
|
+
payload: compactionFailureTurnEventPayload(error51)
|
|
11630
11814
|
},
|
|
11631
11815
|
{
|
|
11632
11816
|
type: "session.status.changed",
|
|
@@ -11673,6 +11857,22 @@ async function runPostAgentCompaction(deps) {
|
|
|
11673
11857
|
control.activityStatus = "idle";
|
|
11674
11858
|
return { exit: claimedResult({ status: "idle" }) };
|
|
11675
11859
|
}
|
|
11860
|
+
if (remoteCompactionRequester && session.codexCompactionMode === "remote_v2") {
|
|
11861
|
+
const forced = await isSessionCompactionRequested2(db, input.workspaceId, input.sessionId);
|
|
11862
|
+
const thresholdTokens = compactionThresholdTokens2(eventing.modelRunSettings);
|
|
11863
|
+
if (forced || (attempt.triggerType === "user.message" || attempt.triggerType === "system.update.delivered") && (session.lastInputTokens ?? 0) >= thresholdTokens) {
|
|
11864
|
+
queuePreparedCompaction(
|
|
11865
|
+
agent,
|
|
11866
|
+
new CompactionNeededError({
|
|
11867
|
+
trigger: forced ? "operator" : "threshold",
|
|
11868
|
+
signalSource: forced ? "operator" : "provider",
|
|
11869
|
+
signalTokens: session.lastInputTokens ?? 0,
|
|
11870
|
+
thresholdTokens
|
|
11871
|
+
})
|
|
11872
|
+
);
|
|
11873
|
+
}
|
|
11874
|
+
return { ok: { compactSummarizer } };
|
|
11875
|
+
}
|
|
11676
11876
|
if (attempt.triggerType === "user.message" || attempt.triggerType === "system.update.delivered") {
|
|
11677
11877
|
let forced = false;
|
|
11678
11878
|
try {
|
|
@@ -11741,13 +11941,13 @@ async function runPostAgentCompaction(deps) {
|
|
|
11741
11941
|
},
|
|
11742
11942
|
{
|
|
11743
11943
|
clearRequestedCompaction: forced,
|
|
11744
|
-
publishLiveEvents: publishCompactionLiveEvents
|
|
11944
|
+
publishLiveEvents: publishCompactionLiveEvents,
|
|
11945
|
+
providerRejection: compactionProviderRejection2(compactError)
|
|
11745
11946
|
}
|
|
11746
11947
|
);
|
|
11747
11948
|
if (!isCompactionSummaryFailure(compactError)) throw compactError;
|
|
11748
11949
|
const deferredSteer = await settleDeferredSteerAfterCompaction();
|
|
11749
11950
|
if (deferredSteer) return { exit: deferredSteer };
|
|
11750
|
-
const errorMessage = String(compactionFailureReasonFromError(compactError));
|
|
11751
11951
|
observability.error("context compaction failed", {
|
|
11752
11952
|
sessionId: input.sessionId,
|
|
11753
11953
|
turnId: attempt.turnId,
|
|
@@ -11757,13 +11957,7 @@ async function runPostAgentCompaction(deps) {
|
|
|
11757
11957
|
events: [
|
|
11758
11958
|
{
|
|
11759
11959
|
type: "turn.failed",
|
|
11760
|
-
payload:
|
|
11761
|
-
error: errorMessage,
|
|
11762
|
-
code: "context_compaction_failed",
|
|
11763
|
-
retryable: false,
|
|
11764
|
-
recovery: "user_message",
|
|
11765
|
-
compacted: false
|
|
11766
|
-
}
|
|
11960
|
+
payload: compactionFailureTurnEventPayload(compactError)
|
|
11767
11961
|
},
|
|
11768
11962
|
{ type: "session.status.changed", payload: { status: "idle" } }
|
|
11769
11963
|
],
|
|
@@ -11793,7 +11987,8 @@ import {
|
|
|
11793
11987
|
SandboxWorkspaceMutationFencedError
|
|
11794
11988
|
} from "@opengeni/db";
|
|
11795
11989
|
import {
|
|
11796
|
-
RoutingMutationOutcomeUnknownError
|
|
11990
|
+
RoutingMutationOutcomeUnknownError,
|
|
11991
|
+
runManagedCodemodeClientHook
|
|
11797
11992
|
} from "@opengeni/runtime";
|
|
11798
11993
|
import {
|
|
11799
11994
|
sandboxLifecycleTransitionWaitMs,
|
|
@@ -11844,12 +12039,23 @@ function createSandboxTurnRuntime(deps) {
|
|
|
11844
12039
|
sandboxState.machinePrimarySession
|
|
11845
12040
|
);
|
|
11846
12041
|
};
|
|
11847
|
-
const onHomeSandboxRebound = (rebound) => {
|
|
12042
|
+
const onHomeSandboxRebound = async (rebound) => {
|
|
11848
12043
|
const current = sandboxState.resolvedSandbox;
|
|
12044
|
+
if (!current) throw new Error("Home sandbox rebound before turn sandbox admission");
|
|
12045
|
+
if (rebound.established.backendId !== "selfhosted" && rebound.established.instanceId !== current.established.instanceId) {
|
|
12046
|
+
const commandFence = eventing.toolCancellationFenceRef.current;
|
|
12047
|
+
await runWorkspaceMutationForSandbox(
|
|
12048
|
+
{ ...current, established: rebound.established, leaseEpoch: rebound.leaseEpoch },
|
|
12049
|
+
"homeSandboxClientPreparation",
|
|
12050
|
+
() => runManagedCodemodeClientHook(rebound.established.session, {
|
|
12051
|
+
environment: {},
|
|
12052
|
+
...commandFence ? { commandRunner: commandFence.runSandboxCommand.bind(commandFence) } : {}
|
|
12053
|
+
})
|
|
12054
|
+
);
|
|
12055
|
+
}
|
|
11849
12056
|
const previousSession = current?.established.session;
|
|
11850
12057
|
const preserveRoutingProxy = current !== null && previousSession !== sandboxState.setupBoxSession;
|
|
11851
12058
|
sandboxState.setupBoxSession = rebound.established.session;
|
|
11852
|
-
if (!current) return;
|
|
11853
12059
|
current.leaseEpoch = rebound.leaseEpoch;
|
|
11854
12060
|
current.established = preserveRoutingProxy ? {
|
|
11855
12061
|
...current.established,
|
|
@@ -12120,7 +12326,13 @@ function createSandboxTurnRuntime(deps) {
|
|
|
12120
12326
|
deadlineRotationRequested: sandboxState.deadlineRotationRequested
|
|
12121
12327
|
})) {
|
|
12122
12328
|
const snapshot = maybePersistWarmWorkspaceSnapshot(
|
|
12123
|
-
{
|
|
12329
|
+
{
|
|
12330
|
+
db,
|
|
12331
|
+
settings,
|
|
12332
|
+
objectStorage,
|
|
12333
|
+
sandboxMetrics: runtimeMetricsHooksForObservability(observability),
|
|
12334
|
+
observability
|
|
12335
|
+
},
|
|
12124
12336
|
{
|
|
12125
12337
|
accountId: input.accountId,
|
|
12126
12338
|
workspaceId: input.workspaceId,
|
|
@@ -12177,6 +12389,9 @@ import {
|
|
|
12177
12389
|
getLiveEnrollmentConnection,
|
|
12178
12390
|
assertPersonalMachineForAttempt
|
|
12179
12391
|
} from "@opengeni/db";
|
|
12392
|
+
import {
|
|
12393
|
+
sandboxCaptureWaitMetricObserver
|
|
12394
|
+
} from "@opengeni/observability";
|
|
12180
12395
|
import {
|
|
12181
12396
|
withRunCredentialsSession as withRunCredentialsSession2,
|
|
12182
12397
|
runOwnedSandboxSetup as runOwnedSandboxSetup2,
|
|
@@ -12552,6 +12767,7 @@ async function establishTurnSandbox(deps) {
|
|
|
12552
12767
|
bus,
|
|
12553
12768
|
onOp: machineOpObserver.observer,
|
|
12554
12769
|
onSandboxOperation: sandboxOperationObserver,
|
|
12770
|
+
onSandboxCaptureWait: sandboxCaptureWaitMetricObserver(observability),
|
|
12555
12771
|
opJournal
|
|
12556
12772
|
},
|
|
12557
12773
|
{
|
|
@@ -12614,6 +12830,7 @@ async function establishTurnSandbox(deps) {
|
|
|
12614
12830
|
opJournal,
|
|
12615
12831
|
onOp: machineOpObserver.observer,
|
|
12616
12832
|
onSandboxOperation: sandboxOperationObserver,
|
|
12833
|
+
onSandboxCaptureWait: sandboxCaptureWaitMetricObserver(observability),
|
|
12617
12834
|
onHomeSandboxRebound,
|
|
12618
12835
|
...runtimeCancellationSignal ? { waitSignal: runtimeCancellationSignal } : {}
|
|
12619
12836
|
},
|
|
@@ -12820,6 +13037,7 @@ async function establishTurnSandbox(deps) {
|
|
|
12820
13037
|
bus,
|
|
12821
13038
|
opJournal,
|
|
12822
13039
|
onSandboxOperation: sandboxOperationObserver,
|
|
13040
|
+
onSandboxCaptureWait: sandboxCaptureWaitMetricObserver(observability),
|
|
12823
13041
|
onHomeSandboxLost: publishSandboxLost,
|
|
12824
13042
|
onHomeSandboxRebound,
|
|
12825
13043
|
...runtimeCancellationSignal ? { waitSignal: runtimeCancellationSignal } : {}
|
|
@@ -13020,6 +13238,7 @@ async function bindLazySandboxProvisioner(deps) {
|
|
|
13020
13238
|
{
|
|
13021
13239
|
settings: runSettings,
|
|
13022
13240
|
environment: sandboxEnvironment,
|
|
13241
|
+
recordLazyManifest: true,
|
|
13023
13242
|
onRuntimeEvent: async (event) => {
|
|
13024
13243
|
await eventing.publish?.([{ type: event.type, payload: event.payload }], true);
|
|
13025
13244
|
},
|
|
@@ -13121,6 +13340,7 @@ async function bindLazySandboxProvisioner(deps) {
|
|
|
13121
13340
|
opJournal,
|
|
13122
13341
|
onOp: machineOpObserver.observer,
|
|
13123
13342
|
onSandboxOperation: sandboxOperationObserver,
|
|
13343
|
+
onSandboxCaptureWait: sandboxCaptureWaitMetricObserver(observability),
|
|
13124
13344
|
onHomeSandboxLost: publishSandboxLost,
|
|
13125
13345
|
onHomeSandboxRebound,
|
|
13126
13346
|
...runtimeCancellationSignal ? { waitSignal: runtimeCancellationSignal } : {}
|
|
@@ -13966,7 +14186,7 @@ async function prepareRunCredentials(deps) {
|
|
|
13966
14186
|
)
|
|
13967
14187
|
]);
|
|
13968
14188
|
const needsHostCredentialRoot = Boolean(
|
|
13969
|
-
connectionCredentials?.gitCredentials || personalGitHubCredentials
|
|
14189
|
+
connectionCredentials?.gitCredentials || personalGitHubCredentials
|
|
13970
14190
|
);
|
|
13971
14191
|
const hostCredentialRootSessionId = needsHostCredentialRoot ? await getSessionRootId2(db, input.workspaceId, input.sessionId) : null;
|
|
13972
14192
|
if (needsHostCredentialRoot && !hostCredentialRootSessionId) {
|
|
@@ -14336,7 +14556,6 @@ async function prepareRunCredentials(deps) {
|
|
|
14336
14556
|
initialRunCredentialMaterial,
|
|
14337
14557
|
runCredentialsNote,
|
|
14338
14558
|
authorizeGitHubTokenMint,
|
|
14339
|
-
hostCredentialRootSessionId,
|
|
14340
14559
|
gitCredentialAuthority,
|
|
14341
14560
|
codemodeAuthority,
|
|
14342
14561
|
sandboxArtifactRuntime,
|
|
@@ -14442,7 +14661,7 @@ import { getWorkspaceConnectionModelRestrictions } from "@opengeni/db";
|
|
|
14442
14661
|
import {
|
|
14443
14662
|
beginConnectorActionExecution,
|
|
14444
14663
|
getExternalLinkTurnAuthorization,
|
|
14445
|
-
getSessionTurnForAttempt
|
|
14664
|
+
getSessionTurnForAttempt,
|
|
14446
14665
|
getWorkspaceVideoGenerationPolicy,
|
|
14447
14666
|
listSkillDescriptors as listSkillDescriptors2,
|
|
14448
14667
|
completeConnectorActionExecution,
|
|
@@ -14516,15 +14735,14 @@ async function resolveGoogleDrivePublicationTarget(db, workspace, delegations, p
|
|
|
14516
14735
|
);
|
|
14517
14736
|
if (frozen.length !== 1) return null;
|
|
14518
14737
|
const delegation = frozen[0];
|
|
14519
|
-
|
|
14520
|
-
if (!activated && !await ports.getMembership(db, {
|
|
14738
|
+
if (!await ports.getMembership(db, {
|
|
14521
14739
|
accountId: workspace.accountId,
|
|
14522
14740
|
workspaceId,
|
|
14523
14741
|
subjectId: delegation.ownerSubjectId
|
|
14524
14742
|
})) {
|
|
14525
14743
|
return null;
|
|
14526
14744
|
}
|
|
14527
|
-
const originWorkspaceId =
|
|
14745
|
+
const originWorkspaceId = delegation.originWorkspaceId;
|
|
14528
14746
|
if (!originWorkspaceId) return null;
|
|
14529
14747
|
const connection = await ports.getConnection(
|
|
14530
14748
|
db,
|
|
@@ -15075,23 +15293,17 @@ function driveQuery(value) {
|
|
|
15075
15293
|
}
|
|
15076
15294
|
|
|
15077
15295
|
// src/activities/mcp-credentials.ts
|
|
15296
|
+
import { stableJson as stableJson2 } from "@opengeni/contracts";
|
|
15078
15297
|
import {
|
|
15079
15298
|
buildConnectionTokenResolver,
|
|
15080
|
-
|
|
15081
|
-
getSessionTurnForAttempt,
|
|
15082
|
-
authorizeDirectHostMcpUse,
|
|
15083
|
-
resolveAcceptedHostMcpBinding,
|
|
15084
|
-
resolveAcceptedConnectionUse,
|
|
15085
|
-
sessionTenancyProductActivated
|
|
15299
|
+
resolveAcceptedConnectionUse
|
|
15086
15300
|
} from "@opengeni/db";
|
|
15087
|
-
import { recordTenancyCompatibilityLaneUse } from "@opengeni/observability";
|
|
15088
15301
|
|
|
15089
15302
|
// src/activities/mcp-operation-authority.ts
|
|
15090
15303
|
import { createHash as createHash10 } from "crypto";
|
|
15091
15304
|
import { stableJson } from "@opengeni/contracts";
|
|
15092
15305
|
function mcpOperationAuthorityDigest(request, authority) {
|
|
15093
15306
|
const n = authority.native;
|
|
15094
|
-
const h = authority.host;
|
|
15095
15307
|
const ref = request.connectionRef;
|
|
15096
15308
|
const metadata = {
|
|
15097
15309
|
version: 1,
|
|
@@ -15105,14 +15317,13 @@ function mcpOperationAuthorityDigest(request, authority) {
|
|
|
15105
15317
|
providerDomain: ref.providerDomain,
|
|
15106
15318
|
kind: ref.kind,
|
|
15107
15319
|
subjectScope: ref.subjectScope,
|
|
15108
|
-
hostBinding: ref.hostBinding,
|
|
15109
15320
|
scopes: ref.scopes ? [...ref.scopes].sort() : void 0,
|
|
15110
15321
|
resource: ref.resource,
|
|
15111
15322
|
selectedResources: ref.selectedResources ? [...ref.selectedResources].sort(
|
|
15112
15323
|
(a, b) => stableJson(a) < stableJson(b) ? -1 : stableJson(a) > stableJson(b) ? 1 : 0
|
|
15113
15324
|
) : void 0
|
|
15114
15325
|
},
|
|
15115
|
-
native:
|
|
15326
|
+
native: {
|
|
15116
15327
|
organizationId: n.organizationId,
|
|
15117
15328
|
workspaceId: n.workspaceId,
|
|
15118
15329
|
sessionId: n.sessionId,
|
|
@@ -15122,87 +15333,28 @@ function mcpOperationAuthorityDigest(request, authority) {
|
|
|
15122
15333
|
ownerSubjectId: n.ownerSubjectId,
|
|
15123
15334
|
authorityId: n.authorityId,
|
|
15124
15335
|
grantId: n.grantId,
|
|
15125
|
-
principal:
|
|
15126
|
-
}
|
|
15127
|
-
host: h ? {
|
|
15128
|
-
accountId: h.accountId,
|
|
15129
|
-
workspaceId: h.workspaceId,
|
|
15130
|
-
targetSessionId: h.targetSessionId,
|
|
15131
|
-
targetSessionVisibility: h.targetSessionVisibility,
|
|
15132
|
-
targetSessionAuthorityEpoch: h.targetSessionAuthorityEpoch,
|
|
15133
|
-
ownerSubjectId: h.ownerSubjectId,
|
|
15134
|
-
ownerOrganizationMembershipId: h.ownerOrganizationMembershipId,
|
|
15135
|
-
ownerMembershipAuthorizationRevision: h.ownerMembershipAuthorizationRevision,
|
|
15136
|
-
bindingId: h.bindingId,
|
|
15137
|
-
bindingGeneration: h.bindingGeneration,
|
|
15138
|
-
definition: h.definition,
|
|
15139
|
-
delegationId: h.delegationId,
|
|
15140
|
-
delegationGeneration: h.delegationGeneration
|
|
15141
|
-
} : void 0
|
|
15336
|
+
principal: authority.principal
|
|
15337
|
+
}
|
|
15142
15338
|
};
|
|
15143
15339
|
return createHash10("sha256").update(stableJson(metadata)).digest("hex");
|
|
15144
15340
|
}
|
|
15145
15341
|
|
|
15146
15342
|
// src/activities/mcp-credentials.ts
|
|
15147
|
-
var OPENGENI_CONNECTION_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu;
|
|
15148
15343
|
function connectionTokenResolverForTurn(input) {
|
|
15149
|
-
|
|
15150
|
-
|
|
15151
|
-
|
|
15152
|
-
|
|
15344
|
+
return bindNativeConnectionCredentialsToTurn(
|
|
15345
|
+
input,
|
|
15346
|
+
buildConnectionTokenResolver(input.db, input.settings)
|
|
15347
|
+
);
|
|
15348
|
+
}
|
|
15349
|
+
function bindNativeConnectionCredentialsToTurn(input, nativeResolver) {
|
|
15153
15350
|
const recoveryEnabled = (serverId) => input.settings.mcpServers.some(
|
|
15154
15351
|
(server) => server.id === serverId && "operationRecovery" in server && server.operationRecovery !== void 0 && Object.keys(server.operationRecovery ?? {}).length > 0
|
|
15155
15352
|
);
|
|
15156
|
-
const
|
|
15157
|
-
|
|
15158
|
-
|
|
15159
|
-
const resolver = buildHostConnectionTokenResolver(hostResolver, {
|
|
15160
|
-
accountId: input.accountId,
|
|
15161
|
-
workspaceId: input.workspaceId,
|
|
15162
|
-
sessionId: input.sessionId,
|
|
15163
|
-
rootSessionId: input.rootSessionId,
|
|
15164
|
-
turnId: input.turn.id,
|
|
15165
|
-
attemptId: input.attemptId,
|
|
15166
|
-
executionGeneration: input.turn.executionGeneration,
|
|
15167
|
-
initiator: input.turn.initiator,
|
|
15168
|
-
initiatorContext: input.turn.initiatorContext,
|
|
15169
|
-
surface: "model",
|
|
15170
|
-
resolveAcceptedBinding: (request) => resolveAcceptedHostMcpBinding(hostDb, request),
|
|
15171
|
-
// Only immutable captured direct-turn authority is currently supported.
|
|
15172
|
-
// Direct, scheduled and exact causal/child snapshots are validated;
|
|
15173
|
-
// no authority follows merely from a binding or creator identity.
|
|
15174
|
-
authorizeDurableBinding: (request) => authorizeDirectHostMcpUse(
|
|
15175
|
-
hostDb,
|
|
15176
|
-
request,
|
|
15177
|
-
wantsDigest ? (snapshot) => {
|
|
15178
|
-
authorizedSnapshot = snapshot;
|
|
15179
|
-
} : void 0
|
|
15180
|
-
),
|
|
15181
|
-
authorizeExecution: async (request) => {
|
|
15182
|
-
if (request.connectionRef.authoritySource !== "host" && (!request.connectionRef.connectionId || OPENGENI_CONNECTION_ID_PATTERN.test(request.connectionRef.connectionId)))
|
|
15183
|
-
return true;
|
|
15184
|
-
if (!request.attemptId) return false;
|
|
15185
|
-
const current = await readHostTurn(
|
|
15186
|
-
hostDb,
|
|
15187
|
-
request.workspaceId,
|
|
15188
|
-
request.sessionId,
|
|
15189
|
-
request.attemptId
|
|
15190
|
-
);
|
|
15191
|
-
return current !== null && current.id === request.turnId && current.executionGeneration === request.executionGeneration;
|
|
15192
|
-
}
|
|
15193
|
-
});
|
|
15194
|
-
const result = await resolver(credentialRequest);
|
|
15195
|
-
return result.status === "ok" && authorizedSnapshot ? {
|
|
15196
|
-
...result,
|
|
15197
|
-
operationAuthorityDigest: mcpOperationAuthorityDigest(credentialRequest, {
|
|
15198
|
-
host: authorizedSnapshot
|
|
15199
|
-
})
|
|
15200
|
-
} : result;
|
|
15201
|
-
} : nativeResolver;
|
|
15202
|
-
const baseResolver = (request) => input.connectionCredentials?.mcpAuthoritySource === "host" && request.connectionRef.authoritySource !== "host" ? nativeResolver(request) : configuredResolver(request);
|
|
15353
|
+
const canonicalMcpServerIds = new Set(
|
|
15354
|
+
input.canonicalMcpServerIds ?? input.settings.mcpServers.filter((server) => server.connectionRef).map((server) => server.id)
|
|
15355
|
+
);
|
|
15203
15356
|
return async (request) => {
|
|
15204
15357
|
if (request.connectionRef.authoritySource === "host") {
|
|
15205
|
-
if (hostResolver) return await baseResolver(request);
|
|
15206
15358
|
return {
|
|
15207
15359
|
status: "auth_needed",
|
|
15208
15360
|
reason: "unsupported_auth",
|
|
@@ -15215,22 +15367,15 @@ function connectionTokenResolverForTurn(input) {
|
|
|
15215
15367
|
...request.connectionRef.selectedResources ? { selectedResources: request.connectionRef.selectedResources } : {}
|
|
15216
15368
|
};
|
|
15217
15369
|
}
|
|
15218
|
-
|
|
15219
|
-
|
|
15220
|
-
|
|
15221
|
-
|
|
15222
|
-
|
|
15223
|
-
|
|
15224
|
-
|
|
15225
|
-
|
|
15226
|
-
|
|
15227
|
-
...request.connectionRef.provider ? { provider: request.connectionRef.provider } : {},
|
|
15228
|
-
connectionId: request.connectionRef.connectionId,
|
|
15229
|
-
...request.connectionRef.scopes ? { scopes: request.connectionRef.scopes } : {},
|
|
15230
|
-
...request.connectionRef.resource ? { resource: request.connectionRef.resource } : {},
|
|
15231
|
-
...request.connectionRef.selectedResources ? { selectedResources: request.connectionRef.selectedResources } : {}
|
|
15232
|
-
};
|
|
15233
|
-
}
|
|
15370
|
+
const accountBindings = input.turn.mcpAccountBindings ?? [];
|
|
15371
|
+
const accountBinding = accountBindings.find((binding) => binding.serverId === request.serverId);
|
|
15372
|
+
if (input.turn.mcpAccountBindings != null && !accountBinding && canonicalMcpServerIds.has(request.serverId) || !accountBinding && accountBindings.some((binding) => binding.canonicalServerId === request.serverId) || accountBinding && (request.connectionRef.connectionId !== accountBinding.connectionId || request.connectionRef.providerDomain !== accountBinding.providerDomain || request.connectionRef.kind !== accountBinding.kind || request.connectionRef.subjectScope !== accountBinding.subjectScope || stableJson2(request.connectionRef) !== stableJson2(accountBinding.connectionRef) || accountBinding.subjectScope === "subject" && request.subjectId !== accountBinding.ownerSubjectId)) {
|
|
15373
|
+
return {
|
|
15374
|
+
status: "auth_needed",
|
|
15375
|
+
reason: "personal_authority_unavailable",
|
|
15376
|
+
providerDomain: request.connectionRef.providerDomain,
|
|
15377
|
+
...request.connectionRef.provider ? { provider: request.connectionRef.provider } : {}
|
|
15378
|
+
};
|
|
15234
15379
|
}
|
|
15235
15380
|
const acceptedDelegation = input.turn.personalConnectionDelegations.find(
|
|
15236
15381
|
(delegation) => (delegation.connectionType === void 0 || delegation.connectionType === "mcp" || delegation.connectionType === "github_personal" && delegation.serverId === "github:personal" && request.serverId === "github:personal" && request.connectionRef.provider === "github" && request.connectionRef.kind === "oauth2" && request.connectionRef.providerDomain === "github.com" && request.credentialTarget === "http_api" && isGitHubApiDestination(request.destinationUrl)) && delegation.serverId === request.serverId && delegation.connectionId === request.connectionRef.connectionId
|
|
@@ -15245,19 +15390,12 @@ function connectionTokenResolverForTurn(input) {
|
|
|
15245
15390
|
};
|
|
15246
15391
|
}
|
|
15247
15392
|
if (subjectScope === "workspace" && !request.connectionRef.connectionId) {
|
|
15248
|
-
|
|
15249
|
-
|
|
15250
|
-
|
|
15251
|
-
|
|
15252
|
-
|
|
15253
|
-
|
|
15254
|
-
reason: "missing_connection",
|
|
15255
|
-
providerDomain: request.connectionRef.providerDomain,
|
|
15256
|
-
...request.connectionRef.provider ? { provider: request.connectionRef.provider } : {}
|
|
15257
|
-
};
|
|
15258
|
-
}
|
|
15259
|
-
recordTenancyCompatibilityLaneUse(input.observability, "connection_pre_snapshot_ref");
|
|
15260
|
-
return await baseResolver(request);
|
|
15393
|
+
return {
|
|
15394
|
+
status: "auth_needed",
|
|
15395
|
+
reason: "missing_connection",
|
|
15396
|
+
providerDomain: request.connectionRef.providerDomain,
|
|
15397
|
+
...request.connectionRef.provider ? { provider: request.connectionRef.provider } : {}
|
|
15398
|
+
};
|
|
15261
15399
|
}
|
|
15262
15400
|
const credentialUseContext = {
|
|
15263
15401
|
accountId: input.accountId,
|
|
@@ -15299,51 +15437,32 @@ function connectionTokenResolverForTurn(input) {
|
|
|
15299
15437
|
})
|
|
15300
15438
|
} : {},
|
|
15301
15439
|
authorizeProviderRequest: async () => {
|
|
15302
|
-
const
|
|
15440
|
+
const authorization = await authorize({
|
|
15303
15441
|
...credentialUseContext,
|
|
15304
15442
|
physicalRequestId: crypto.randomUUID(),
|
|
15305
15443
|
usePhase: "provider_request"
|
|
15306
15444
|
});
|
|
15307
|
-
return
|
|
15445
|
+
return authorization.status === "authorized";
|
|
15308
15446
|
}
|
|
15309
15447
|
};
|
|
15310
15448
|
};
|
|
15311
|
-
const
|
|
15312
|
-
|
|
15313
|
-
|
|
15314
|
-
}
|
|
15315
|
-
|
|
15316
|
-
|
|
15317
|
-
|
|
15318
|
-
|
|
15319
|
-
|
|
15320
|
-
|
|
15321
|
-
if (result2.status === "ok") recordAuthorizedScope(result2.connectionUseAttribution?.scope);
|
|
15322
|
-
return withProviderRequestAuthorization(result2);
|
|
15323
|
-
}
|
|
15324
|
-
const authorization = await authorize(credentialUseContext);
|
|
15325
|
-
if (authorization.status === "denied") {
|
|
15449
|
+
const { subjectId: requestSubjectId, ...requestWithoutSubject } = request;
|
|
15450
|
+
const result = await nativeResolver({
|
|
15451
|
+
...requestWithoutSubject,
|
|
15452
|
+
...accountBinding?.connectionAuthorityGeneration !== void 0 ? { expectedAuthorityGeneration: accountBinding.connectionAuthorityGeneration } : {},
|
|
15453
|
+
// Workspace authority has no personal owner, even when the turn has a
|
|
15454
|
+
// causal human. Do not pass that human as credential ownership context.
|
|
15455
|
+
...accountBinding?.subjectScope !== "workspace" && requestSubjectId !== void 0 ? { subjectId: requestSubjectId } : {},
|
|
15456
|
+
connectionUseContext: credentialUseContext
|
|
15457
|
+
});
|
|
15458
|
+
if (accountBinding && result.status === "ok" && result.connectionId !== accountBinding.connectionId) {
|
|
15326
15459
|
return {
|
|
15327
15460
|
status: "auth_needed",
|
|
15328
|
-
reason:
|
|
15329
|
-
providerDomain:
|
|
15330
|
-
...request.connectionRef.provider ? { provider: request.connectionRef.provider } : {}
|
|
15461
|
+
reason: "personal_authority_unavailable",
|
|
15462
|
+
providerDomain: accountBinding.providerDomain
|
|
15331
15463
|
};
|
|
15332
15464
|
}
|
|
15333
|
-
|
|
15334
|
-
const result = await baseResolver({
|
|
15335
|
-
...request,
|
|
15336
|
-
connectionUseContext: credentialUseContext,
|
|
15337
|
-
connectionUseAuthority: authorization.attribution,
|
|
15338
|
-
connectionRef: {
|
|
15339
|
-
...request.connectionRef,
|
|
15340
|
-
connectionId: authorization.attribution.connectionId,
|
|
15341
|
-
kind: authorization.connectionKind,
|
|
15342
|
-
subjectScope: authorization.attribution.scope === "workspace" ? "workspace" : "subject"
|
|
15343
|
-
},
|
|
15344
|
-
...authorization.attribution.ownerSubjectId ? { subjectId: authorization.attribution.ownerSubjectId } : {}
|
|
15345
|
-
});
|
|
15346
|
-
return withProviderRequestAuthorization(result, authorization.attribution);
|
|
15465
|
+
return withProviderRequestAuthorization(result);
|
|
15347
15466
|
};
|
|
15348
15467
|
}
|
|
15349
15468
|
function isGitHubApiDestination(value) {
|
|
@@ -15355,6 +15474,100 @@ function isGitHubApiDestination(value) {
|
|
|
15355
15474
|
}
|
|
15356
15475
|
}
|
|
15357
15476
|
|
|
15477
|
+
// src/activities/mcp-account-routes.ts
|
|
15478
|
+
function accountRouteAuthNeededPayload(payload, bindings) {
|
|
15479
|
+
const binding = bindings?.find((candidate) => candidate.serverId === payload.serverId);
|
|
15480
|
+
return binding ? {
|
|
15481
|
+
...payload,
|
|
15482
|
+
canonicalServerId: binding.canonicalServerId,
|
|
15483
|
+
connectionSubjectScope: binding.subjectScope
|
|
15484
|
+
} : payload;
|
|
15485
|
+
}
|
|
15486
|
+
function expandMcpAccountRoutes(input) {
|
|
15487
|
+
if (input.bindings == null) {
|
|
15488
|
+
return { settings: input.settings, tools: input.tools, accountLabels: /* @__PURE__ */ new Map() };
|
|
15489
|
+
}
|
|
15490
|
+
const configured = new Map(input.settings.mcpServers.map((server) => [server.id, server]));
|
|
15491
|
+
const byCanonical = /* @__PURE__ */ new Map();
|
|
15492
|
+
const routes = /* @__PURE__ */ new Set();
|
|
15493
|
+
const accounts = /* @__PURE__ */ new Set();
|
|
15494
|
+
for (const binding of input.bindings) {
|
|
15495
|
+
const account = JSON.stringify([binding.canonicalServerId, binding.connectionId]);
|
|
15496
|
+
if (routes.has(binding.serverId) || accounts.has(account) || configured.has(binding.serverId) || binding.subjectScope === "subject" !== (binding.ownerSubjectId !== null) || binding.connectionRef.authoritySource === "host" || binding.connectionRef.connectionId !== binding.connectionId || binding.connectionRef.subjectScope !== binding.subjectScope || binding.connectionRef.providerDomain !== binding.providerDomain || binding.connectionRef.kind !== binding.kind) {
|
|
15497
|
+
throw new Error("Invalid accepted MCP account route");
|
|
15498
|
+
}
|
|
15499
|
+
routes.add(binding.serverId);
|
|
15500
|
+
accounts.add(account);
|
|
15501
|
+
const siblings = byCanonical.get(binding.canonicalServerId) ?? [];
|
|
15502
|
+
siblings.push(binding);
|
|
15503
|
+
byCanonical.set(binding.canonicalServerId, siblings);
|
|
15504
|
+
}
|
|
15505
|
+
const servers = [];
|
|
15506
|
+
const tools = [];
|
|
15507
|
+
const accountLabels = /* @__PURE__ */ new Map();
|
|
15508
|
+
for (const tool of input.tools) {
|
|
15509
|
+
const bindings = byCanonical.get(tool.id);
|
|
15510
|
+
if (!bindings) {
|
|
15511
|
+
if (!configured.get(tool.id)?.connectionRef) tools.push(tool);
|
|
15512
|
+
continue;
|
|
15513
|
+
}
|
|
15514
|
+
const canonical = configured.get(tool.id);
|
|
15515
|
+
if (!canonical?.connectionRef) {
|
|
15516
|
+
throw new Error("Accepted MCP account route has no canonical connection configuration");
|
|
15517
|
+
}
|
|
15518
|
+
for (const binding of bindings) {
|
|
15519
|
+
if (canonical.connectionRef.authoritySource === "host" || canonical.connectionRef.providerDomain !== binding.providerDomain || canonical.connectionRef.kind && canonical.connectionRef.kind !== binding.kind) {
|
|
15520
|
+
throw new Error("Accepted MCP account route does not match canonical provider");
|
|
15521
|
+
}
|
|
15522
|
+
const { headers: _headers, ...config2 } = canonical;
|
|
15523
|
+
const label = `${canonical.name ?? canonical.id} \u2014 ${binding.subjectScope === "subject" ? "Personal" : "Workspace"}: ${binding.accountLabel}`;
|
|
15524
|
+
servers.push({
|
|
15525
|
+
...config2,
|
|
15526
|
+
id: binding.serverId,
|
|
15527
|
+
name: label,
|
|
15528
|
+
connectionRef: structuredClone(binding.connectionRef)
|
|
15529
|
+
});
|
|
15530
|
+
tools.push({ ...tool, id: binding.serverId });
|
|
15531
|
+
accountLabels.set(binding.serverId, label);
|
|
15532
|
+
}
|
|
15533
|
+
}
|
|
15534
|
+
return {
|
|
15535
|
+
settings: {
|
|
15536
|
+
...input.settings,
|
|
15537
|
+
mcpServers: [
|
|
15538
|
+
...input.settings.mcpServers.filter((server) => !server.connectionRef),
|
|
15539
|
+
...servers
|
|
15540
|
+
]
|
|
15541
|
+
},
|
|
15542
|
+
tools,
|
|
15543
|
+
accountLabels
|
|
15544
|
+
};
|
|
15545
|
+
}
|
|
15546
|
+
function expandApiIntegrationAccountRoutes(input) {
|
|
15547
|
+
const selected = new Set(input.tools.map((tool) => tool.id));
|
|
15548
|
+
if (input.bindings == null)
|
|
15549
|
+
return input.integrations.filter((item) => selected.has(item.serverId));
|
|
15550
|
+
const acceptedBindings = input.bindings;
|
|
15551
|
+
return input.integrations.flatMap((integration) => {
|
|
15552
|
+
const bindings = acceptedBindings.filter(
|
|
15553
|
+
(binding) => binding.canonicalServerId === integration.serverId
|
|
15554
|
+
);
|
|
15555
|
+
if (bindings.length === 0)
|
|
15556
|
+
return !integration.connectionRef && selected.has(integration.serverId) ? [integration] : [];
|
|
15557
|
+
return bindings.filter((binding) => selected.has(binding.serverId)).map((binding) => {
|
|
15558
|
+
if (binding.connectionAuthorityGeneration === void 0) {
|
|
15559
|
+
throw new Error("Accepted API integration account route has no authority generation");
|
|
15560
|
+
}
|
|
15561
|
+
return {
|
|
15562
|
+
...integration,
|
|
15563
|
+
serverId: binding.serverId,
|
|
15564
|
+
connectionRef: structuredClone(binding.connectionRef),
|
|
15565
|
+
connectionAuthorityGeneration: binding.connectionAuthorityGeneration
|
|
15566
|
+
};
|
|
15567
|
+
});
|
|
15568
|
+
});
|
|
15569
|
+
}
|
|
15570
|
+
|
|
15358
15571
|
// src/activities/agent-turn/tool-environment.ts
|
|
15359
15572
|
import { createMcpOperationPersistence } from "@opengeni/db/mcp-operations";
|
|
15360
15573
|
|
|
@@ -30486,7 +30699,7 @@ function exactPersonalDelegation(delegations) {
|
|
|
30486
30699
|
(delegation2) => delegation2.serverId === PERSONAL_GITHUB_DELEGATION_SERVER_ID && delegation2.connectionType === "github_personal"
|
|
30487
30700
|
);
|
|
30488
30701
|
const delegation = matches[0];
|
|
30489
|
-
if (matches.length !== 1 || !delegation || delegation.providerDomain !== "github.com" || delegation.kind !== "oauth2" || !delegation.originWorkspaceId || !delegation.
|
|
30702
|
+
if (matches.length !== 1 || !delegation || delegation.providerDomain !== "github.com" || delegation.kind !== "oauth2" || !delegation.originWorkspaceId || !delegation.personalGitHubRepositorySelection) {
|
|
30490
30703
|
throw new GitHubRestAuthorityError("Personal GitHub delegation is unavailable");
|
|
30491
30704
|
}
|
|
30492
30705
|
return delegation;
|
|
@@ -30686,7 +30899,7 @@ async function materializeConnectorAttachmentsInChannel(channel, request, option
|
|
|
30686
30899
|
}
|
|
30687
30900
|
|
|
30688
30901
|
// src/activities/agent-turn/tool-environment.ts
|
|
30689
|
-
import { allowedFirstPartyMcpToolsForSession
|
|
30902
|
+
import { allowedFirstPartyMcpToolsForSession } from "@opengeni/config";
|
|
30690
30903
|
|
|
30691
30904
|
// src/activities/codemode-dispatcher.ts
|
|
30692
30905
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
@@ -31080,7 +31293,7 @@ function safeErrorMessage(error51) {
|
|
|
31080
31293
|
// src/activities/agent-turn/tool-environment.ts
|
|
31081
31294
|
import { CODEX_CLIENT_VERSION } from "@opengeni/codex";
|
|
31082
31295
|
import {
|
|
31083
|
-
|
|
31296
|
+
workspaceSessionToolPolicyDefaultServerIds,
|
|
31084
31297
|
loadRigDefaultVariableSetEnvironment,
|
|
31085
31298
|
mergeRigDefaultVariableSetEnvironment,
|
|
31086
31299
|
buildApiIntegrationMcpServers,
|
|
@@ -31093,24 +31306,9 @@ import {
|
|
|
31093
31306
|
import { SandboxChannelAService as SandboxChannelAService3 } from "@opengeni/runtime/sandbox";
|
|
31094
31307
|
import { sandboxRunAs as sandboxRunAs4 } from "@opengeni/runtime";
|
|
31095
31308
|
import {
|
|
31096
|
-
DEFAULT_FIRST_PARTY_MCP_PERMISSIONS as
|
|
31309
|
+
DEFAULT_FIRST_PARTY_MCP_PERMISSIONS as DEFAULT_FIRST_PARTY_MCP_PERMISSIONS2
|
|
31097
31310
|
} from "@opengeni/contracts";
|
|
31098
31311
|
|
|
31099
|
-
// src/activities/agent-turn/turn-sandbox-access.ts
|
|
31100
|
-
async function resolveTurnSandboxAccess(sandboxState, sdkOwnedSandboxSession, unavailableMessage) {
|
|
31101
|
-
let sandbox = sandboxState.resolvedSandbox;
|
|
31102
|
-
if (!sandbox && sandboxState.turnSandboxProvisioner) {
|
|
31103
|
-
sandbox = await sandboxState.turnSandboxProvisioner.get();
|
|
31104
|
-
}
|
|
31105
|
-
const session = sandboxState.lazyOwnedSandbox?.session ?? sandbox?.established.session ?? sdkOwnedSandboxSession;
|
|
31106
|
-
if (!session) throw new Error(unavailableMessage);
|
|
31107
|
-
return {
|
|
31108
|
-
sandbox,
|
|
31109
|
-
session,
|
|
31110
|
-
leaseEpoch: sandbox?.leaseEpoch ?? 0
|
|
31111
|
-
};
|
|
31112
|
-
}
|
|
31113
|
-
|
|
31114
31312
|
// src/activities/agent-turn/list-models.ts
|
|
31115
31313
|
import {
|
|
31116
31314
|
compareModelPickerOrder,
|
|
@@ -31204,7 +31402,8 @@ import {
|
|
|
31204
31402
|
portableSkillPluginKey,
|
|
31205
31403
|
readSkill,
|
|
31206
31404
|
resolveSkillImport,
|
|
31207
|
-
saveSkill
|
|
31405
|
+
saveSkill,
|
|
31406
|
+
removeSkill
|
|
31208
31407
|
} from "@opengeni/core";
|
|
31209
31408
|
import {
|
|
31210
31409
|
buildPortableSkillArtifact as buildPortableSkillArtifact3,
|
|
@@ -31369,7 +31568,7 @@ function createSkillSaveAttemptToolDefinition(input) {
|
|
|
31369
31568
|
modelName: "skill_save",
|
|
31370
31569
|
codemodePath: ["opengeni", "skill_save"],
|
|
31371
31570
|
title: "Save Skill text",
|
|
31372
|
-
description: "Create or edit a
|
|
31571
|
+
description: "Create or edit a Skill for reusable procedures or context-specific and personal behavioral preferences, not retrieval-only facts. Put its applicability in the SKILL.md description so the prompt index can guide skill_read; the full body is loaded when relevant. Short always-on workspace rules use instruction_policy_save. Supply only changed UTF-8 text files and explicit deletions; omitted files are preserved. No sandbox is needed. Use the revision and scope version returned by Skill discovery for stale-write protection. For creation choose a new UUID, set expectedRevisionId to null and expectedScopeVersion to 1. The effective Skills setting governs publication: Automatic publishes, Review first saves a pending revision in Knowledge > Needs review while the task continues, and Off prevents agent authoring. Report the actual receipt without asking an approval question. Private chats save personal Skills; shared chats save workspace Skills. Preserve the intended scope; another destination is not a workaround for unavailable scope or learning restrictions.",
|
|
31373
31572
|
inputSchema: {
|
|
31374
31573
|
type: "object",
|
|
31375
31574
|
properties: {
|
|
@@ -31492,6 +31691,43 @@ function createSkillInstallAttemptToolDefinition(input) {
|
|
|
31492
31691
|
};
|
|
31493
31692
|
}
|
|
31494
31693
|
|
|
31694
|
+
// src/activities/agent-turn/skill-remove.ts
|
|
31695
|
+
var SkillRemoveRequest = external_exports.object({
|
|
31696
|
+
operationId: external_exports.uuid(),
|
|
31697
|
+
skillId: external_exports.uuid(),
|
|
31698
|
+
expectedRevisionId: external_exports.uuid().nullable(),
|
|
31699
|
+
expectedScopeVersion: external_exports.number().int().positive(),
|
|
31700
|
+
reason: external_exports.string().min(1).max(2e3)
|
|
31701
|
+
}).strict();
|
|
31702
|
+
function createSkillRemoveAttemptToolDefinition(input) {
|
|
31703
|
+
return {
|
|
31704
|
+
identity: { serverId: "opengeni", toolName: "skill_remove" },
|
|
31705
|
+
modelName: "skill_remove",
|
|
31706
|
+
codemodePath: ["opengeni", "skill_remove"],
|
|
31707
|
+
title: "Permanently remove Skill",
|
|
31708
|
+
description: "Permanently delete a saved Skill and ALL its stored revisions, not a recoverable hide. Conversations remain unchanged. Read the exact Skill first; supply its current active revision and scope version. Built-in, repository and inline session Skills cannot be removed. Automatic applies deletion; Review first retains an explicitly labeled deletion proposal for human review in Knowledge > Needs review; Off refuses changes. Reuse the same operationId and exact arguments after an uncertain result. Never report a pending proposal as deleted.",
|
|
31709
|
+
inputSchema: JSON.parse(JSON.stringify(external_exports.toJSONSchema(SkillRemoveRequest))),
|
|
31710
|
+
annotations: {
|
|
31711
|
+
readOnlyHint: false,
|
|
31712
|
+
destructiveHint: true,
|
|
31713
|
+
idempotentHint: true,
|
|
31714
|
+
openWorldHint: false
|
|
31715
|
+
},
|
|
31716
|
+
source: "opengeni",
|
|
31717
|
+
approval: "none",
|
|
31718
|
+
execute: async (args) => {
|
|
31719
|
+
await input.authorize();
|
|
31720
|
+
const output = await input.remove(SkillRemoveRequest.parse(args));
|
|
31721
|
+
const text = JSON.stringify(output);
|
|
31722
|
+
return {
|
|
31723
|
+
isError: false,
|
|
31724
|
+
content: [{ type: "text", text }],
|
|
31725
|
+
structuredContent: JSON.parse(text)
|
|
31726
|
+
};
|
|
31727
|
+
}
|
|
31728
|
+
};
|
|
31729
|
+
}
|
|
31730
|
+
|
|
31495
31731
|
// src/activities/agent-turn/skill-transfer.ts
|
|
31496
31732
|
import { posix } from "path";
|
|
31497
31733
|
import {
|
|
@@ -31768,6 +32004,12 @@ function createWorkspaceSkillTools(input) {
|
|
|
31768
32004
|
);
|
|
31769
32005
|
};
|
|
31770
32006
|
return [
|
|
32007
|
+
createSkillRemoveAttemptToolDefinition({
|
|
32008
|
+
authorize,
|
|
32009
|
+
remove: async (request) => withReviewState(
|
|
32010
|
+
await removeSkill(input.db, { ...context, ...request, actor: input.actor })
|
|
32011
|
+
)
|
|
32012
|
+
}),
|
|
31771
32013
|
createSkillReadAttemptToolDefinition({ authorize, load }),
|
|
31772
32014
|
createSkillSearchAttemptToolDefinition({
|
|
31773
32015
|
authorize,
|
|
@@ -31784,7 +32026,7 @@ function createWorkspaceSkillTools(input) {
|
|
|
31784
32026
|
id: entry.id,
|
|
31785
32027
|
name: entry.artifact.name,
|
|
31786
32028
|
description: entry.artifact.description || entry.artifact.name,
|
|
31787
|
-
source: entry.id.startsWith("builtin:") ? "builtin" :
|
|
32029
|
+
source: entry.id.startsWith("builtin:") ? "builtin" : "session"
|
|
31788
32030
|
}))
|
|
31789
32031
|
],
|
|
31790
32032
|
publicSearch: createPublicSkillSearchClient(input.settings)
|
|
@@ -31904,6 +32146,8 @@ function configuredBundledSkillNames(context) {
|
|
|
31904
32146
|
const tools = new Set(context.firstPartyTools);
|
|
31905
32147
|
const artifacts = () => tools.has("editable_artifact_list") && tools.has("editable_artifact_get");
|
|
31906
32148
|
const definitions = [
|
|
32149
|
+
{ name: "opengeni-help", include: () => true },
|
|
32150
|
+
{ name: "opengeni-client", include: () => true },
|
|
31907
32151
|
{ name: "opengeni-visualize", include: () => true },
|
|
31908
32152
|
{ name: "document-parsing", include: () => true },
|
|
31909
32153
|
{ name: "opengeni-skills", include: () => true },
|
|
@@ -31962,7 +32206,12 @@ async function prepareTurnToolPolicy(deps) {
|
|
|
31962
32206
|
toolPolicy: session.toolPolicy,
|
|
31963
32207
|
sessionTools: scheduledEffectiveMcpServerIds ? turn.tools : session.tools,
|
|
31964
32208
|
availableMcpServerIds: scheduledEffectiveMcpServerIds ? scheduledEffectiveMcpServerIds.filter((id) => currentMcpServerIds.has(id)) : [...currentMcpServerIds],
|
|
31965
|
-
defaultMcpServerIds: scheduledEffectiveMcpServerIds ??
|
|
32209
|
+
defaultMcpServerIds: scheduledEffectiveMcpServerIds ?? (session.toolPolicy.mode === "workspace_default" ? await workspaceSessionToolPolicyDefaultServerIds(
|
|
32210
|
+
db,
|
|
32211
|
+
input.workspaceId,
|
|
32212
|
+
capabilitySettings,
|
|
32213
|
+
fileAuthoritySubjectId ?? void 0
|
|
32214
|
+
) : [])
|
|
31966
32215
|
});
|
|
31967
32216
|
const mcpAvailabilityNote = unavailableMcpOperationalContext({
|
|
31968
32217
|
droppedIds: resolvedToolPolicy.effectivePolicy.droppedIds,
|
|
@@ -32064,7 +32313,6 @@ async function prepareTurnToolRuntime(deps) {
|
|
|
32064
32313
|
objectStorage,
|
|
32065
32314
|
observability,
|
|
32066
32315
|
cancellationSignal,
|
|
32067
|
-
connectionCredentials,
|
|
32068
32316
|
eventing,
|
|
32069
32317
|
attempt,
|
|
32070
32318
|
sandboxState,
|
|
@@ -32076,10 +32324,9 @@ async function prepareTurnToolRuntime(deps) {
|
|
|
32076
32324
|
codexAppsCredentialId,
|
|
32077
32325
|
turnExecutionPolicy,
|
|
32078
32326
|
trigger,
|
|
32079
|
-
runSettings,
|
|
32327
|
+
runSettings: canonicalRunSettings,
|
|
32080
32328
|
lazyToolTransport,
|
|
32081
|
-
turnTools,
|
|
32082
|
-
hostCredentialRootSessionId,
|
|
32329
|
+
turnTools: canonicalTurnTools,
|
|
32083
32330
|
sandboxArtifactRuntime,
|
|
32084
32331
|
activeSandboxBackend,
|
|
32085
32332
|
groupBoxBackend,
|
|
@@ -32091,21 +32338,25 @@ async function prepareTurnToolRuntime(deps) {
|
|
|
32091
32338
|
throwIfWorkerShuttingDown,
|
|
32092
32339
|
throwIfTurnCancelled
|
|
32093
32340
|
} = deps;
|
|
32341
|
+
const accountRoutes = expandMcpAccountRoutes({
|
|
32342
|
+
settings: canonicalRunSettings,
|
|
32343
|
+
tools: canonicalTurnTools,
|
|
32344
|
+
bindings: turn.mcpAccountBindings
|
|
32345
|
+
});
|
|
32346
|
+
const runSettings = accountRoutes.settings;
|
|
32347
|
+
const turnTools = accountRoutes.tools;
|
|
32094
32348
|
const toolContextPreparationStartedAt = performance.now();
|
|
32095
32349
|
throwIfWorkerShuttingDown();
|
|
32096
32350
|
throwIfTurnCancelled();
|
|
32097
|
-
const mcpCredentialRootSessionId = connectionCredentials?.mcpCredentials && hostCredentialRootSessionId ? hostCredentialRootSessionId : input.sessionId;
|
|
32098
32351
|
const rawResolveCredential = connectionTokenResolverForTurn({
|
|
32099
32352
|
db,
|
|
32100
32353
|
settings: runSettings,
|
|
32101
|
-
|
|
32354
|
+
canonicalMcpServerIds: canonicalRunSettings.mcpServers.filter((server) => server.connectionRef).map((server) => server.id),
|
|
32102
32355
|
accountId: input.accountId,
|
|
32103
32356
|
workspaceId: input.workspaceId,
|
|
32104
32357
|
sessionId: input.sessionId,
|
|
32105
|
-
rootSessionId: mcpCredentialRootSessionId,
|
|
32106
32358
|
attemptId: input.attemptId,
|
|
32107
|
-
turn
|
|
32108
|
-
observability
|
|
32359
|
+
turn
|
|
32109
32360
|
});
|
|
32110
32361
|
const personalConnectionDelegations = turn.personalConnectionDelegations;
|
|
32111
32362
|
const delegatedMembershipChecks = /* @__PURE__ */ new Map();
|
|
@@ -32163,16 +32414,24 @@ async function prepareTurnToolRuntime(deps) {
|
|
|
32163
32414
|
return;
|
|
32164
32415
|
}
|
|
32165
32416
|
await eventing.publish(
|
|
32166
|
-
[
|
|
32417
|
+
[
|
|
32418
|
+
{
|
|
32419
|
+
type: "tool.auth_needed",
|
|
32420
|
+
payload: rollingSafeToolAuthNeededPayload(
|
|
32421
|
+
accountRouteAuthNeededPayload(payload, turn.mcpAccountBindings)
|
|
32422
|
+
)
|
|
32423
|
+
}
|
|
32424
|
+
],
|
|
32167
32425
|
true
|
|
32168
32426
|
);
|
|
32169
32427
|
};
|
|
32170
|
-
const selectedApiIntegrationServerIds = new Set(turnTools.map((tool) => tool.id));
|
|
32171
32428
|
const apiIntegrationMcpServers = buildApiIntegrationMcpServers({
|
|
32172
32429
|
settings: runSettings,
|
|
32173
|
-
integrations:
|
|
32174
|
-
|
|
32175
|
-
|
|
32430
|
+
integrations: expandApiIntegrationAccountRoutes({
|
|
32431
|
+
integrations: installedApiIntegrations,
|
|
32432
|
+
bindings: turn.mcpAccountBindings,
|
|
32433
|
+
tools: turnTools
|
|
32434
|
+
}),
|
|
32176
32435
|
authority: {
|
|
32177
32436
|
accountId: input.accountId,
|
|
32178
32437
|
workspaceId: input.workspaceId,
|
|
@@ -32230,10 +32489,10 @@ async function prepareTurnToolRuntime(deps) {
|
|
|
32230
32489
|
);
|
|
32231
32490
|
if (linkedAuthority && !linkedAuthority.authorized)
|
|
32232
32491
|
throw new Error("Native identity link was revoked");
|
|
32233
|
-
const effectiveFirstPartyPermissions = linkedAuthority ? (session.firstPartyMcpPermissions ??
|
|
32492
|
+
const effectiveFirstPartyPermissions = linkedAuthority ? (session.firstPartyMcpPermissions ?? DEFAULT_FIRST_PARTY_MCP_PERMISSIONS2).filter(
|
|
32234
32493
|
(permission) => hasPermission2(linkedAuthority.permissions, permission)
|
|
32235
32494
|
) : session.firstPartyMcpPermissions;
|
|
32236
|
-
const selectedFirstPartyMcpTools =
|
|
32495
|
+
const selectedFirstPartyMcpTools = allowedFirstPartyMcpToolsForSession(
|
|
32237
32496
|
runSettings,
|
|
32238
32497
|
session.firstPartyMcpTools
|
|
32239
32498
|
);
|
|
@@ -32249,10 +32508,10 @@ async function prepareTurnToolRuntime(deps) {
|
|
|
32249
32508
|
parallelGenerationAvailable: typeof runtime.generateSessionTitle === "function"
|
|
32250
32509
|
});
|
|
32251
32510
|
const googleDrivePublicationAllowed = selectedFirstPartyMcpTools.includes("editable_artifact_export") && selectedFirstPartyMcpTools.includes("editable_artifact_export_status") && hasPermission2(
|
|
32252
|
-
[...effectiveFirstPartyPermissions ??
|
|
32511
|
+
[...effectiveFirstPartyPermissions ?? DEFAULT_FIRST_PARTY_MCP_PERMISSIONS2],
|
|
32253
32512
|
"artifacts:read"
|
|
32254
32513
|
) && hasPermission2(
|
|
32255
|
-
[...effectiveFirstPartyPermissions ??
|
|
32514
|
+
[...effectiveFirstPartyPermissions ?? DEFAULT_FIRST_PARTY_MCP_PERMISSIONS2],
|
|
32256
32515
|
"artifacts:publish"
|
|
32257
32516
|
);
|
|
32258
32517
|
const googleDriveConnectorBindings = googleDrivePublicationTool && googleDrivePublicationTarget && googleDrivePublicationAllowed ? [
|
|
@@ -32289,7 +32548,6 @@ async function prepareTurnToolRuntime(deps) {
|
|
|
32289
32548
|
});
|
|
32290
32549
|
const selectedSkills = [
|
|
32291
32550
|
...bundledSkills,
|
|
32292
|
-
...deps.selectedSkillActivations.map((entry) => ({ id: entry.id, artifact: entry.artifact })),
|
|
32293
32551
|
...session.skills.map((skill) => ({
|
|
32294
32552
|
id: `session:${session.id}:${skill.name}`,
|
|
32295
32553
|
artifact: skill
|
|
@@ -32391,7 +32649,7 @@ async function prepareTurnToolRuntime(deps) {
|
|
|
32391
32649
|
assertAttempt: async () => {
|
|
32392
32650
|
throwIfWorkerShuttingDown();
|
|
32393
32651
|
throwIfTurnCancelled();
|
|
32394
|
-
const current = await
|
|
32652
|
+
const current = await getSessionTurnForAttempt(
|
|
32395
32653
|
db,
|
|
32396
32654
|
input.workspaceId,
|
|
32397
32655
|
input.sessionId,
|
|
@@ -32597,6 +32855,7 @@ async function prepareTurnToolRuntime(deps) {
|
|
|
32597
32855
|
try {
|
|
32598
32856
|
eventing.preparedTools = await waitForTurnOperation(
|
|
32599
32857
|
runtime.prepareTools(githubRestMcp.settings, githubRestMcp.tools, {
|
|
32858
|
+
mcpAccountLabels: accountRoutes.accountLabels,
|
|
32600
32859
|
accountId: input.accountId,
|
|
32601
32860
|
workspaceId: input.workspaceId,
|
|
32602
32861
|
sessionId: input.sessionId,
|
|
@@ -32614,7 +32873,7 @@ async function prepareTurnToolRuntime(deps) {
|
|
|
32614
32873
|
...operationPersistence ? { mcpOperationPersistence: operationPersistence } : {},
|
|
32615
32874
|
...linkedAuthority ? {
|
|
32616
32875
|
authorizeAttemptExecution: async () => {
|
|
32617
|
-
const current = await
|
|
32876
|
+
const current = await getSessionTurnForAttempt(
|
|
32618
32877
|
db,
|
|
32619
32878
|
input.workspaceId,
|
|
32620
32879
|
input.sessionId,
|
|
@@ -32636,13 +32895,10 @@ async function prepareTurnToolRuntime(deps) {
|
|
|
32636
32895
|
localMcpServers,
|
|
32637
32896
|
...deferNonEagerToolPreparation ? { deferNonEagerUntilToolDemand: true } : {},
|
|
32638
32897
|
onPreparationPhase: (measurement) => {
|
|
32639
|
-
|
|
32640
|
-
|
|
32898
|
+
recordToolPreparationPhase(observability, {
|
|
32899
|
+
...measurement,
|
|
32641
32900
|
provider: turnExecutionPolicy.providerId,
|
|
32642
|
-
backend: activeSandboxBackend ?? groupBoxBackend
|
|
32643
|
-
outcome: measurement.outcome,
|
|
32644
|
-
durationSeconds: measurement.durationSeconds,
|
|
32645
|
-
count: githubRestMcp.tools.length
|
|
32901
|
+
backend: activeSandboxBackend ?? groupBoxBackend
|
|
32646
32902
|
});
|
|
32647
32903
|
},
|
|
32648
32904
|
onAttemptToolCatalog: async (catalog) => {
|
|
@@ -32920,7 +33176,9 @@ import {
|
|
|
32920
33176
|
getWorkspaceVideoGenerationPolicy as getWorkspaceVideoGenerationPolicy2,
|
|
32921
33177
|
loadWorkspaceVercelAiGatewayCredentialLease,
|
|
32922
33178
|
getExternalLinkTurnAuthorization as getExternalLinkTurnAuthorization2,
|
|
32923
|
-
getSessionTurnForAttempt as
|
|
33179
|
+
getSessionTurnForAttempt as getSessionTurnForAttempt2,
|
|
33180
|
+
ensureSessionReasoningConfiguration,
|
|
33181
|
+
ensureSessionSkillCatalog
|
|
32924
33182
|
} from "@opengeni/db";
|
|
32925
33183
|
import {
|
|
32926
33184
|
formatSkillCatalog
|
|
@@ -32931,6 +33189,7 @@ import {
|
|
|
32931
33189
|
WORKSPACE_GATEWAY_PROVIDER_ID as WORKSPACE_GATEWAY_PROVIDER_ID2,
|
|
32932
33190
|
resolveModelProvider as resolveModelProvider2
|
|
32933
33191
|
} from "@opengeni/config";
|
|
33192
|
+
import { supportsReasoningConfiguration as supportsReasoningConfiguration2 } from "@opengeni/codex";
|
|
32934
33193
|
|
|
32935
33194
|
// src/activities/xai-image-generation.ts
|
|
32936
33195
|
import {
|
|
@@ -34144,6 +34403,11 @@ async function buildTurnAgent(deps) {
|
|
|
34144
34403
|
codexContext
|
|
34145
34404
|
} = deps;
|
|
34146
34405
|
const preparedTools = eventing.preparedTools;
|
|
34406
|
+
const sessionInstructions = await recoveryAwareSessionInstructions(
|
|
34407
|
+
db,
|
|
34408
|
+
input.workspaceId,
|
|
34409
|
+
session
|
|
34410
|
+
);
|
|
34147
34411
|
const missingSessionTitleHint = preparationIndependentToolNames.includes(
|
|
34148
34412
|
SESSION_TITLE_MODEL_TOOL_NAME
|
|
34149
34413
|
);
|
|
@@ -34455,7 +34719,15 @@ async function buildTurnAgent(deps) {
|
|
|
34455
34719
|
turnExecutionPolicy.latencyMode
|
|
34456
34720
|
);
|
|
34457
34721
|
const approvedToolCallId = approvedConnectorActionCallId(trigger);
|
|
34458
|
-
const modelVisibleSkillCatalogText =
|
|
34722
|
+
const modelVisibleSkillCatalogText = await ensureSessionSkillCatalog(db, {
|
|
34723
|
+
accountId: input.accountId,
|
|
34724
|
+
workspaceId: input.workspaceId,
|
|
34725
|
+
sessionId: input.sessionId,
|
|
34726
|
+
turnId: turn.id,
|
|
34727
|
+
expectedExecutionGeneration: turn.executionGeneration,
|
|
34728
|
+
expectedAttemptId: input.attemptId,
|
|
34729
|
+
catalog: formatSkillCatalog(deps.skillCatalog)
|
|
34730
|
+
});
|
|
34459
34731
|
try {
|
|
34460
34732
|
eventing.companyBrainContextContributions = summarizeCompanyBrainContributions(
|
|
34461
34733
|
buildCompanyBrainContributionReceiptFor(modelVisibleSkillCatalogText)
|
|
@@ -34479,6 +34751,16 @@ async function buildTurnAgent(deps) {
|
|
|
34479
34751
|
);
|
|
34480
34752
|
if (linkedToolAuthority && !linkedToolAuthority.authorized)
|
|
34481
34753
|
throw new Error("Native identity link was revoked");
|
|
34754
|
+
const useReasoningUpdates = eventing.modelRunSettings.reasoningConfigurationUpdatesEnabled && resolvedModel?.provider.api === "responses" && (resolvedModel.provider.id === "codex" || resolvedModel.provider.id === "openai") && supportsReasoningConfiguration2(turnExecutionPolicy.upstreamModelId, turn.reasoningEffort);
|
|
34755
|
+
const requestReasoningEffort = useReasoningUpdates && supportsReasoningConfiguration2(turnExecutionPolicy.upstreamModelId, turn.reasoningEffort) ? await ensureSessionReasoningConfiguration(db, {
|
|
34756
|
+
accountId: input.accountId,
|
|
34757
|
+
workspaceId: input.workspaceId,
|
|
34758
|
+
sessionId: input.sessionId,
|
|
34759
|
+
turnId: turn.id,
|
|
34760
|
+
expectedExecutionGeneration: turn.executionGeneration,
|
|
34761
|
+
expectedAttemptId: input.attemptId,
|
|
34762
|
+
effort: turn.reasoningEffort
|
|
34763
|
+
}) : turn.reasoningEffort;
|
|
34482
34764
|
const agent = (() => {
|
|
34483
34765
|
const agentConstructionStartedAt = performance.now();
|
|
34484
34766
|
let agentConstructionOutcome = "completed";
|
|
@@ -34486,7 +34768,7 @@ async function buildTurnAgent(deps) {
|
|
|
34486
34768
|
return runtime.buildAgent(eventing.modelRunSettings, runtimeResources, {
|
|
34487
34769
|
...linkedToolAuthority ? {
|
|
34488
34770
|
authorizeAttemptExecution: async () => {
|
|
34489
|
-
const current = await
|
|
34771
|
+
const current = await getSessionTurnForAttempt2(
|
|
34490
34772
|
db,
|
|
34491
34773
|
input.workspaceId,
|
|
34492
34774
|
input.sessionId,
|
|
@@ -34497,7 +34779,7 @@ async function buildTurnAgent(deps) {
|
|
|
34497
34779
|
}
|
|
34498
34780
|
} : {},
|
|
34499
34781
|
...preparedTools.inputWaitYield ? { inputWaitYield: preparedTools.inputWaitYield } : {},
|
|
34500
|
-
reasoningEffort:
|
|
34782
|
+
reasoningEffort: requestReasoningEffort,
|
|
34501
34783
|
latencyMode: turnExecutionPolicy.latencyMode,
|
|
34502
34784
|
...serviceTier ? { serviceTier } : {},
|
|
34503
34785
|
...humanInputResume ? { humanInputResponse: humanInputResume } : {},
|
|
@@ -34582,13 +34864,14 @@ async function buildTurnAgent(deps) {
|
|
|
34582
34864
|
),
|
|
34583
34865
|
onRetainableSessionImageOutput: media.retainSessionImageAtToolBoundary,
|
|
34584
34866
|
skillCatalog: deps.skillCatalog,
|
|
34867
|
+
skillCatalogInHistory: true,
|
|
34585
34868
|
...!structuredWorkspacePolicyActive && workspaceAgentInstructions ? { instructionsTemplate: workspaceAgentInstructions } : {},
|
|
34586
34869
|
...workspaceGovernance ? { workspaceGovernance } : {},
|
|
34587
34870
|
...workspaceMemory ? { workspaceMemory } : {},
|
|
34588
34871
|
// Per-session persona tier (session > workspace > deployment default).
|
|
34589
34872
|
// Composed system-level AFTER the workspace persona so it refines it for
|
|
34590
34873
|
// this one session; absent ⇒ byte-identical to today's composition.
|
|
34591
|
-
...
|
|
34874
|
+
...sessionInstructions ? { sessionInstructions } : {},
|
|
34592
34875
|
...workspaceEnvironmentOption,
|
|
34593
34876
|
// RIG RUNTIME (M3): the doctrine block, the setup-script hook (only when
|
|
34594
34877
|
// the frozen version carries a non-empty script), and the rig credential
|
|
@@ -34687,7 +34970,7 @@ function createRunAgentTurnActivity(services) {
|
|
|
34687
34970
|
});
|
|
34688
34971
|
const modelCheckpointMemoryCollector = createModelCheckpointMemoryCollector();
|
|
34689
34972
|
const turnCompletionMemoryCollector = createModelCheckpointMemoryCollector();
|
|
34690
|
-
|
|
34973
|
+
const runAgentTurn = async (input, resolvedServices, activitySpan) => {
|
|
34691
34974
|
const {
|
|
34692
34975
|
settings,
|
|
34693
34976
|
catalogSourceSettings = settings,
|
|
@@ -34704,7 +34987,7 @@ function createRunAgentTurnActivity(services) {
|
|
|
34704
34987
|
connectionCredentials,
|
|
34705
34988
|
personalGitHubCredentials,
|
|
34706
34989
|
startVideoGenerationWorkflow
|
|
34707
|
-
} =
|
|
34990
|
+
} = resolvedServices;
|
|
34708
34991
|
const activityContext = currentActivityContext();
|
|
34709
34992
|
const cancellationSignal = activityContext?.cancellationSignal;
|
|
34710
34993
|
const sandboxResumeController = new AbortController();
|
|
@@ -34732,11 +35015,6 @@ function createRunAgentTurnActivity(services) {
|
|
|
34732
35015
|
});
|
|
34733
35016
|
const dispatchId = activityContext?.info.activityId ?? randomUUID6();
|
|
34734
35017
|
const activityStarted = performance.now();
|
|
34735
|
-
const activitySpan = observability.startSpan("worker.run_agent_segment", {
|
|
34736
|
-
"opengeni.session_id": input.sessionId,
|
|
34737
|
-
"opengeni.workflow_id": input.workflowId,
|
|
34738
|
-
"opengeni.trigger_kind": input.trigger.kind
|
|
34739
|
-
});
|
|
34740
35018
|
const acknowledgeLostAttemptOwnership = () => {
|
|
34741
35019
|
control.acknowledgeQuiescence = true;
|
|
34742
35020
|
noteCancellationRequested();
|
|
@@ -34757,7 +35035,7 @@ function createRunAgentTurnActivity(services) {
|
|
|
34757
35035
|
const machineOpObserver = makeMachineOpObserver(
|
|
34758
35036
|
runtimeMetricsHooksForObservability(observability)
|
|
34759
35037
|
);
|
|
34760
|
-
const sandboxOperationObserver =
|
|
35038
|
+
const sandboxOperationObserver = sandboxOperationMetricObserver2(observability);
|
|
34761
35039
|
const setLastInputTokensFenced = async (lastInputTokens) => {
|
|
34762
35040
|
if (!attempt.turnId || attempt.executionGeneration <= 0) {
|
|
34763
35041
|
throw new Error("Turn attempt was not initialized before token accounting");
|
|
@@ -34918,8 +35196,26 @@ function createRunAgentTurnActivity(services) {
|
|
|
34918
35196
|
executionGeneration: attempt.executionGeneration
|
|
34919
35197
|
}
|
|
34920
35198
|
});
|
|
35199
|
+
const attachmentAuthority = await getSessionAuthorityProjection(
|
|
35200
|
+
db,
|
|
35201
|
+
input.workspaceId,
|
|
35202
|
+
input.sessionId
|
|
35203
|
+
);
|
|
35204
|
+
if (!attachmentAuthority) throw new Error("Session attachment authority unavailable");
|
|
34921
35205
|
return await withSessionRlsActorContext(
|
|
34922
35206
|
{
|
|
35207
|
+
sessionAttachmentReadAccess: {
|
|
35208
|
+
sessionId: input.sessionId,
|
|
35209
|
+
authorityEpoch: attachmentAuthority.authorityEpoch,
|
|
35210
|
+
actor: {
|
|
35211
|
+
kind: "agent_attempt",
|
|
35212
|
+
subjectId: "service:agent-turn",
|
|
35213
|
+
callerSessionId: input.sessionId,
|
|
35214
|
+
turnId: attempt.turnId,
|
|
35215
|
+
attemptId: input.attemptId,
|
|
35216
|
+
executionGeneration: attempt.executionGeneration
|
|
35217
|
+
}
|
|
35218
|
+
},
|
|
34923
35219
|
subjectId: "service:agent-turn",
|
|
34924
35220
|
initiatingHumanSubjectId: fileAuthoritySubjectId,
|
|
34925
35221
|
privateFileOwnerSubjectId: learning.defaultScope === "personal" ? learning.subjectId : null
|
|
@@ -34987,7 +35283,6 @@ function createRunAgentTurnActivity(services) {
|
|
|
34987
35283
|
});
|
|
34988
35284
|
const {
|
|
34989
35285
|
runtimePreparationStartedAt,
|
|
34990
|
-
packRuntime,
|
|
34991
35286
|
rigVersion,
|
|
34992
35287
|
rigName,
|
|
34993
35288
|
agentHumanInputEnabled,
|
|
@@ -35017,7 +35312,13 @@ function createRunAgentTurnActivity(services) {
|
|
|
35017
35312
|
db,
|
|
35018
35313
|
runSettings,
|
|
35019
35314
|
input.workspaceId,
|
|
35020
|
-
providerTurn.effectiveCodexCredentialId ?? ""
|
|
35315
|
+
providerTurn.effectiveCodexCredentialId ?? "",
|
|
35316
|
+
void 0,
|
|
35317
|
+
{
|
|
35318
|
+
turnId: turn.id,
|
|
35319
|
+
holderId: leases.codex.holderId,
|
|
35320
|
+
generation: leases.codex.generation
|
|
35321
|
+
}
|
|
35021
35322
|
);
|
|
35022
35323
|
const resolveTrackedToken = async (resolve) => {
|
|
35023
35324
|
const token = await resolve();
|
|
@@ -35408,38 +35709,7 @@ These are publication receipts for the human's earlier answer. Do not call the r
|
|
|
35408
35709
|
cancellationSignal?.throwIfAborted();
|
|
35409
35710
|
knowledgeRecoveryNote = "[OpenGeni confirmation recovery unavailable] Do not assume an earlier remember confirmation was published. Inspect the current Knowledge or instruction review.";
|
|
35410
35711
|
}
|
|
35411
|
-
const
|
|
35412
|
-
settings: runSettings,
|
|
35413
|
-
scope: {
|
|
35414
|
-
accountId: input.accountId,
|
|
35415
|
-
workspaceId: input.workspaceId,
|
|
35416
|
-
sessionId: input.sessionId,
|
|
35417
|
-
turnId: turn.id,
|
|
35418
|
-
attemptId: input.attemptId,
|
|
35419
|
-
executionGeneration: attempt.executionGeneration
|
|
35420
|
-
},
|
|
35421
|
-
// Only attachments on this accepted turn are new source inputs.
|
|
35422
|
-
// Session-level file receipts remain historical context and must
|
|
35423
|
-
// never trigger metadata reads, downloads, or re-preparation.
|
|
35424
|
-
resources: turn.resources,
|
|
35425
|
-
selectedTools: session.firstPartyMcpTools,
|
|
35426
|
-
permissions: session.firstPartyMcpPermissions,
|
|
35427
|
-
learningMode: learning.effective.knowledge,
|
|
35428
|
-
signal: cancellationSignal,
|
|
35429
|
-
onOutcome: async (outcome) => {
|
|
35430
|
-
if (outcome.status === "disabled") return;
|
|
35431
|
-
await eventing.publish(
|
|
35432
|
-
[
|
|
35433
|
-
{
|
|
35434
|
-
type: outcome.status === "failed" ? "knowledge.source.failed" : "knowledge.source.prepared",
|
|
35435
|
-
payload: outcome
|
|
35436
|
-
}
|
|
35437
|
-
],
|
|
35438
|
-
true
|
|
35439
|
-
);
|
|
35440
|
-
}
|
|
35441
|
-
});
|
|
35442
|
-
const knowledgeSourcePreparationNote = [knowledgeRecoveryNote, attachmentPreparationNote].filter(Boolean).join("\n\n") || void 0;
|
|
35712
|
+
const knowledgeSourcePreparationNote = knowledgeRecoveryNote;
|
|
35443
35713
|
const sandboxRoute = await resolveSandboxRoute({
|
|
35444
35714
|
input,
|
|
35445
35715
|
settings,
|
|
@@ -35510,7 +35780,6 @@ These are publication receipts for the human's earlier answer. Do not call the r
|
|
|
35510
35780
|
establishPolicy,
|
|
35511
35781
|
initialRunCredentialMaterial,
|
|
35512
35782
|
runCredentialsNote,
|
|
35513
|
-
hostCredentialRootSessionId,
|
|
35514
35783
|
codemodeAuthority,
|
|
35515
35784
|
sandboxArtifactRuntime,
|
|
35516
35785
|
sandboxEnvironment,
|
|
@@ -35628,7 +35897,6 @@ These are publication receipts for the human's earlier answer. Do not call the r
|
|
|
35628
35897
|
];
|
|
35629
35898
|
const toolRuntime = await prepareTurnToolRuntime({
|
|
35630
35899
|
fetchKnowledgeSource: sourceActivities.runKnowledgeSourceSyncBatch,
|
|
35631
|
-
selectedSkillActivations: packRuntime.skillActivations,
|
|
35632
35900
|
input,
|
|
35633
35901
|
catalogSourceSettings,
|
|
35634
35902
|
db,
|
|
@@ -35637,7 +35905,6 @@ These are publication receipts for the human's earlier answer. Do not call the r
|
|
|
35637
35905
|
objectStorage,
|
|
35638
35906
|
observability,
|
|
35639
35907
|
cancellationSignal,
|
|
35640
|
-
connectionCredentials,
|
|
35641
35908
|
eventing,
|
|
35642
35909
|
attempt,
|
|
35643
35910
|
sandboxState,
|
|
@@ -35655,7 +35922,6 @@ These are publication receipts for the human's earlier answer. Do not call the r
|
|
|
35655
35922
|
lazyToolTransport,
|
|
35656
35923
|
turnTools,
|
|
35657
35924
|
connectionScope,
|
|
35658
|
-
hostCredentialRootSessionId,
|
|
35659
35925
|
sandboxArtifactRuntime,
|
|
35660
35926
|
activeSandboxBackend,
|
|
35661
35927
|
groupBoxBackend,
|
|
@@ -36103,6 +36369,36 @@ These are publication receipts for the human's earlier answer. Do not call the r
|
|
|
36103
36369
|
});
|
|
36104
36370
|
}
|
|
36105
36371
|
};
|
|
36372
|
+
return async (input) => {
|
|
36373
|
+
const resolvedServices = await services();
|
|
36374
|
+
const correlationId = turnExecutionTelemetryKey2(
|
|
36375
|
+
input.workspaceId,
|
|
36376
|
+
input.sessionId,
|
|
36377
|
+
input.attemptId
|
|
36378
|
+
);
|
|
36379
|
+
const span = resolvedServices.observability.startSpan(
|
|
36380
|
+
"worker.run_agent_segment",
|
|
36381
|
+
{
|
|
36382
|
+
"opengeni.trigger_kind": input.trigger.kind,
|
|
36383
|
+
correlationId
|
|
36384
|
+
},
|
|
36385
|
+
{ parent: null }
|
|
36386
|
+
);
|
|
36387
|
+
try {
|
|
36388
|
+
return await withTraceContext(span, () => {
|
|
36389
|
+
try {
|
|
36390
|
+
resolvedServices.observability.info("worker execution started", { correlationId });
|
|
36391
|
+
} catch {
|
|
36392
|
+
}
|
|
36393
|
+
return runAgentTurn(input, resolvedServices, span);
|
|
36394
|
+
});
|
|
36395
|
+
} catch (error51) {
|
|
36396
|
+
span.end({ error: error51 });
|
|
36397
|
+
throw error51;
|
|
36398
|
+
} finally {
|
|
36399
|
+
span.end();
|
|
36400
|
+
}
|
|
36401
|
+
};
|
|
36106
36402
|
}
|
|
36107
36403
|
|
|
36108
36404
|
// src/activities/video-generation-reconciliation.ts
|
|
@@ -37202,4 +37498,4 @@ export {
|
|
|
37202
37498
|
createTurnActivities,
|
|
37203
37499
|
createTurnActivitiesFromServices
|
|
37204
37500
|
};
|
|
37205
|
-
//# sourceMappingURL=activities-turn-
|
|
37501
|
+
//# sourceMappingURL=activities-turn-2B3WMHBB.js.map
|