@opengeni/db 0.13.4 → 0.14.3
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/{chunk-IQOXTFKA.js → chunk-DW24CKCT.js} +22 -10
- package/dist/chunk-DW24CKCT.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +492 -145
- package/dist/index.js.map +1 -1
- package/dist/provision-roles.d.ts +70 -15
- package/dist/{schema-SbaSoRdr.d.ts → schema-DhkRhcuQ.d.ts} +52 -16
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +1 -1
- package/drizzle/0134_session_first_party_mcp_tools.sql +15 -0
- package/drizzle/0135_durable_machine_input_batches.sql +359 -0
- package/drizzle/0136_unified_session_tool_policy.sql +109 -0
- package/package.json +3 -3
- package/src/index.ts +642 -151
- package/src/schema.ts +28 -10
- package/src/session-queue-commands.ts +30 -54
- package/dist/chunk-IQOXTFKA.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -76,7 +76,7 @@ import {
|
|
|
76
76
|
workspaceVariableSetVariables,
|
|
77
77
|
workspaceVariableSets,
|
|
78
78
|
workspaces
|
|
79
|
-
} from "./chunk-
|
|
79
|
+
} from "./chunk-DW24CKCT.js";
|
|
80
80
|
import {
|
|
81
81
|
migrate,
|
|
82
82
|
runMigrations
|
|
@@ -100,7 +100,10 @@ import {
|
|
|
100
100
|
import "./chunk-PZ5AY32C.js";
|
|
101
101
|
|
|
102
102
|
// src/index.ts
|
|
103
|
-
import {
|
|
103
|
+
import {
|
|
104
|
+
DEFAULT_FIRST_PARTY_MCP_TOOLS,
|
|
105
|
+
SESSION_AUTHORIZATION_LIST_SCOPE_MAX_IDS
|
|
106
|
+
} from "@opengeni/contracts";
|
|
104
107
|
import {
|
|
105
108
|
approvalIdentifier,
|
|
106
109
|
boundWorkspaceControlEvent as boundWorkspaceControlEvent2,
|
|
@@ -119,6 +122,7 @@ import {
|
|
|
119
122
|
RigChange as RigChangeContract,
|
|
120
123
|
SessionGoal as SessionGoalContract,
|
|
121
124
|
SessionSystemUpdatePayload,
|
|
125
|
+
sessionSystemUpdateBatchHistoryItem,
|
|
122
126
|
HostEventExport as HostEventExportContract,
|
|
123
127
|
HostEventExportBatch as HostEventExportBatchContract,
|
|
124
128
|
HostExportConsumerId,
|
|
@@ -2759,7 +2763,6 @@ import { sql as sql5 } from "drizzle-orm";
|
|
|
2759
2763
|
import {
|
|
2760
2764
|
metadataWithTurnExecutionPolicyV1,
|
|
2761
2765
|
mergeResourceRefs,
|
|
2762
|
-
mergeToolRefs,
|
|
2763
2766
|
turnExecutionPolicyAuditMetadata
|
|
2764
2767
|
} from "@opengeni/contracts";
|
|
2765
2768
|
import { and as and5, asc as asc2, eq as eq5, inArray as inArray2, sql as sql3 } from "drizzle-orm";
|
|
@@ -2892,14 +2895,6 @@ async function supersedeSessionCurrentDirectionInTransaction(db, input) {
|
|
|
2892
2895
|
finishedAt: now,
|
|
2893
2896
|
updatedAt: now
|
|
2894
2897
|
}).where(eq5(sessionTurns.id, current.id));
|
|
2895
|
-
await db.update(sessionSystemUpdates).set({ state: "pending", deliveredTurnId: null, deliveredAt: null }).where(
|
|
2896
|
-
and5(
|
|
2897
|
-
eq5(sessionSystemUpdates.workspaceId, input.workspaceId),
|
|
2898
|
-
eq5(sessionSystemUpdates.sessionId, input.sessionId),
|
|
2899
|
-
eq5(sessionSystemUpdates.deliveredTurnId, current.id),
|
|
2900
|
-
eq5(sessionSystemUpdates.state, "delivered")
|
|
2901
|
-
)
|
|
2902
|
-
);
|
|
2903
2898
|
if (current.status === "waiting_capacity") {
|
|
2904
2899
|
await db.update(codexCapacityWaiters).set({ status: "superseded", updatedAt: now }).where(
|
|
2905
2900
|
and5(
|
|
@@ -2965,7 +2960,7 @@ async function normalizeQueuePositions(db, workspaceId, sessionId, orderedIds) {
|
|
|
2965
2960
|
}).where(and5(eq5(sessions.workspaceId, workspaceId), eq5(sessions.id, sessionId)));
|
|
2966
2961
|
}
|
|
2967
2962
|
function draftIsNonEmpty(draft) {
|
|
2968
|
-
return draft.text.length > 0 || draft.resources.length > 0 || draft.
|
|
2963
|
+
return draft.text.length > 0 || draft.resources.length > 0 || draft.sourceTurnId !== null;
|
|
2969
2964
|
}
|
|
2970
2965
|
async function getComposerDraftInTransaction(db, input) {
|
|
2971
2966
|
const query = db.select().from(composerDrafts).where(
|
|
@@ -3005,8 +3000,8 @@ async function saveComposerDraftInTransaction(db, input) {
|
|
|
3005
3000
|
revision,
|
|
3006
3001
|
text: input.text,
|
|
3007
3002
|
resources: input.resources,
|
|
3008
|
-
tools:
|
|
3009
|
-
toolsProvided:
|
|
3003
|
+
tools: [],
|
|
3004
|
+
toolsProvided: false,
|
|
3010
3005
|
model: input.model,
|
|
3011
3006
|
reasoningEffort: input.reasoningEffort,
|
|
3012
3007
|
// A queue edit is still the same accepted work item. Preserve its frozen
|
|
@@ -3305,8 +3300,8 @@ async function editQueuedTurnInTransaction(db, input) {
|
|
|
3305
3300
|
revision: nextDraftRevision,
|
|
3306
3301
|
text: turn.prompt,
|
|
3307
3302
|
resources: turn.resources,
|
|
3308
|
-
tools:
|
|
3309
|
-
toolsProvided:
|
|
3303
|
+
tools: [],
|
|
3304
|
+
toolsProvided: false,
|
|
3310
3305
|
model: turn.model,
|
|
3311
3306
|
reasoningEffort: turn.reasoningEffort,
|
|
3312
3307
|
sourceTurnId: turn.id,
|
|
@@ -3572,8 +3567,6 @@ async function submitHumanPromptInTransaction(db, input) {
|
|
|
3572
3567
|
text: input.text,
|
|
3573
3568
|
turnInstructions: input.turnInstructions ?? null,
|
|
3574
3569
|
resources: input.resources,
|
|
3575
|
-
tools: input.tools,
|
|
3576
|
-
toolsProvided: input.toolsProvided === true,
|
|
3577
3570
|
model: input.model ?? null,
|
|
3578
3571
|
reasoningEffort: input.reasoningEffort ?? null,
|
|
3579
3572
|
source: input.source,
|
|
@@ -3656,15 +3649,11 @@ async function submitHumanPromptInTransaction(db, input) {
|
|
|
3656
3649
|
if (draft && canonicalSessionCommandHash({
|
|
3657
3650
|
text: draft.text,
|
|
3658
3651
|
resources: draft.resources,
|
|
3659
|
-
tools: draft.tools,
|
|
3660
|
-
toolsProvided: draft.toolsProvided,
|
|
3661
3652
|
model: draft.model,
|
|
3662
3653
|
reasoningEffort: draft.reasoningEffort
|
|
3663
3654
|
}) !== canonicalSessionCommandHash({
|
|
3664
3655
|
text: input.text,
|
|
3665
3656
|
resources: input.resources,
|
|
3666
|
-
tools: input.tools,
|
|
3667
|
-
toolsProvided: input.toolsProvided === true,
|
|
3668
3657
|
model: input.model ?? session.model,
|
|
3669
3658
|
reasoningEffort: input.reasoningEffort ?? input.reasoningEffortFallback
|
|
3670
3659
|
})) {
|
|
@@ -3758,7 +3747,6 @@ async function submitHumanPromptInTransaction(db, input) {
|
|
|
3758
3747
|
payload: sanitizeEventPayload({
|
|
3759
3748
|
text: input.text,
|
|
3760
3749
|
...input.resources.length ? { resources: input.resources } : {},
|
|
3761
|
-
...input.toolsProvided === true ? { tools: input.tools } : input.tools.length ? { tools: input.tools } : {},
|
|
3762
3750
|
...input.model ? { model: input.model } : {},
|
|
3763
3751
|
...input.reasoningEffort ? { reasoningEffort: input.reasoningEffort } : {},
|
|
3764
3752
|
delivery: input.delivery,
|
|
@@ -3781,8 +3769,8 @@ async function submitHumanPromptInTransaction(db, input) {
|
|
|
3781
3769
|
prompt: input.text,
|
|
3782
3770
|
turnInstructions: editedSourceTurnInstructions !== void 0 ? editedSourceTurnInstructions : input.turnInstructions ?? null,
|
|
3783
3771
|
resources: input.resources,
|
|
3784
|
-
tools:
|
|
3785
|
-
toolsProvided:
|
|
3772
|
+
tools: [],
|
|
3773
|
+
toolsProvided: false,
|
|
3786
3774
|
model: input.model ?? session.model,
|
|
3787
3775
|
reasoningEffort: input.reasoningEffort ?? input.reasoningEffortFallback,
|
|
3788
3776
|
sandboxBackend: session.sandboxBackend,
|
|
@@ -3902,7 +3890,7 @@ async function submitHumanPromptInTransaction(db, input) {
|
|
|
3902
3890
|
const queueVersion = session.queueVersion + 1;
|
|
3903
3891
|
await db.update(sessions).set({
|
|
3904
3892
|
resources: mergeResourceRefs(session.resources, input.resources),
|
|
3905
|
-
tools:
|
|
3893
|
+
tools: session.tools,
|
|
3906
3894
|
activeTurnId: input.delivery === "steer" ? liveCurrentTurnId : session.activeTurnId,
|
|
3907
3895
|
status: nextStatus,
|
|
3908
3896
|
queueVersion,
|
|
@@ -3966,11 +3954,6 @@ async function submitHumanPromptInTransaction(db, input) {
|
|
|
3966
3954
|
replay: false
|
|
3967
3955
|
};
|
|
3968
3956
|
}
|
|
3969
|
-
function sessionToolPolicyIsFixed(value) {
|
|
3970
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
3971
|
-
const mode = value.mode;
|
|
3972
|
-
return mode === "workspace_default" || mode === "explicit" || mode === "inherited";
|
|
3973
|
-
}
|
|
3974
3957
|
async function sendAgentMessageInTransaction(db, input) {
|
|
3975
3958
|
const workspaceControl = await lockWorkspaceInferenceControl(db, input.workspaceId, "share");
|
|
3976
3959
|
await lockSessionEventWriteRows(db, {
|
|
@@ -4186,14 +4169,14 @@ async function steerAgentSessionInTransaction(db, input) {
|
|
|
4186
4169
|
controlRevision: resumed.revision,
|
|
4187
4170
|
lastSequence: session.lastSequence
|
|
4188
4171
|
});
|
|
4189
|
-
await db.update(sessionSystemUpdates).set({ state: "superseded" }).where(
|
|
4172
|
+
const supersededUpdates = await db.update(sessionSystemUpdates).set({ state: "superseded" }).where(
|
|
4190
4173
|
and5(
|
|
4191
4174
|
eq5(sessionSystemUpdates.workspaceId, input.workspaceId),
|
|
4192
4175
|
eq5(sessionSystemUpdates.sessionId, input.targetSessionId),
|
|
4193
4176
|
eq5(sessionSystemUpdates.kind, "agent_steer_instruction"),
|
|
4194
|
-
|
|
4177
|
+
eq5(sessionSystemUpdates.state, "pending")
|
|
4195
4178
|
)
|
|
4196
|
-
);
|
|
4179
|
+
).returning({ id: sessionSystemUpdates.id });
|
|
4197
4180
|
const now = /* @__PURE__ */ new Date();
|
|
4198
4181
|
const [update] = await db.insert(sessionSystemUpdates).values({
|
|
4199
4182
|
accountId: input.accountId,
|
|
@@ -4252,6 +4235,22 @@ async function steerAgentSessionInTransaction(db, input) {
|
|
|
4252
4235
|
},
|
|
4253
4236
|
occurredAt: now
|
|
4254
4237
|
},
|
|
4238
|
+
...supersededUpdates.length > 0 ? [
|
|
4239
|
+
{
|
|
4240
|
+
accountId: input.accountId,
|
|
4241
|
+
workspaceId: input.workspaceId,
|
|
4242
|
+
sessionId: input.targetSessionId,
|
|
4243
|
+
sequence: ++sequence,
|
|
4244
|
+
type: "system.update.superseded",
|
|
4245
|
+
payload: {
|
|
4246
|
+
updateIds: supersededUpdates.map((entry) => entry.id),
|
|
4247
|
+
count: supersededUpdates.length,
|
|
4248
|
+
replacementUpdateId: update.id,
|
|
4249
|
+
reason: "newer_agent_steer"
|
|
4250
|
+
},
|
|
4251
|
+
occurredAt: now
|
|
4252
|
+
}
|
|
4253
|
+
] : [],
|
|
4255
4254
|
{
|
|
4256
4255
|
accountId: input.accountId,
|
|
4257
4256
|
workspaceId: input.workspaceId,
|
|
@@ -13736,7 +13735,10 @@ async function createSessionInTransaction(tx, input, id) {
|
|
|
13736
13735
|
resources: input.resources,
|
|
13737
13736
|
skills: input.skills ?? [],
|
|
13738
13737
|
tools: input.tools ?? [],
|
|
13739
|
-
toolPolicy: input.toolPolicy ??
|
|
13738
|
+
toolPolicy: input.toolPolicy ?? {
|
|
13739
|
+
mode: "explicit",
|
|
13740
|
+
inheritedFromSessionId: input.parentSessionId ?? null
|
|
13741
|
+
},
|
|
13740
13742
|
metadata: input.metadata,
|
|
13741
13743
|
...creatorColumns(frozenCreator),
|
|
13742
13744
|
model: input.model,
|
|
@@ -13747,6 +13749,7 @@ async function createSessionInTransaction(tx, input, id) {
|
|
|
13747
13749
|
rigId: input.rigId ?? null,
|
|
13748
13750
|
rigVersionId: input.rigVersionId ?? null,
|
|
13749
13751
|
firstPartyMcpPermissions: input.firstPartyMcpPermissions ?? null,
|
|
13752
|
+
firstPartyMcpTools: input.firstPartyMcpTools ?? [...DEFAULT_FIRST_PARTY_MCP_TOOLS],
|
|
13750
13753
|
instructions: input.instructions ?? null,
|
|
13751
13754
|
parentSessionId: input.parentSessionId ?? null,
|
|
13752
13755
|
createIdempotencyKey,
|
|
@@ -20246,6 +20249,56 @@ async function latestWorkspaceCapture(db, workspaceId, sessionId) {
|
|
|
20246
20249
|
return rows.length ? mapWorkspaceCaptureRow(rows[0]) : null;
|
|
20247
20250
|
});
|
|
20248
20251
|
}
|
|
20252
|
+
async function sessionLatestWorkspaceCapture(db, workspaceId, sessionId) {
|
|
20253
|
+
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
20254
|
+
const rows = await scopedDb.execute(sql4`
|
|
20255
|
+
select
|
|
20256
|
+
sessions.id as found_session_id,
|
|
20257
|
+
capture.id as capture_id,
|
|
20258
|
+
capture.session_id as capture_session_id,
|
|
20259
|
+
capture.turn_id as capture_turn_id,
|
|
20260
|
+
capture.revision as capture_revision,
|
|
20261
|
+
capture.lease_epoch as capture_lease_epoch,
|
|
20262
|
+
capture.state as capture_state,
|
|
20263
|
+
capture.manifest_key as capture_manifest_key,
|
|
20264
|
+
capture.tree_index_key as capture_tree_index_key,
|
|
20265
|
+
capture.blob_keys as capture_blob_keys,
|
|
20266
|
+
capture.size_bytes as capture_size_bytes,
|
|
20267
|
+
capture.stats as capture_stats,
|
|
20268
|
+
capture.captured_at as capture_captured_at
|
|
20269
|
+
from sessions
|
|
20270
|
+
left join lateral (
|
|
20271
|
+
select ${WORKSPACE_CAPTURE_COLUMNS}
|
|
20272
|
+
from workspace_captures
|
|
20273
|
+
where workspace_captures.session_id = sessions.id
|
|
20274
|
+
order by workspace_captures.revision desc
|
|
20275
|
+
limit 1
|
|
20276
|
+
) capture on true
|
|
20277
|
+
where sessions.workspace_id = ${workspaceId} and sessions.id = ${sessionId}
|
|
20278
|
+
limit 1
|
|
20279
|
+
`);
|
|
20280
|
+
const row = rows[0];
|
|
20281
|
+
if (!row) return { sessionExists: false, capture: null };
|
|
20282
|
+
if (!row.capture_id) return { sessionExists: true, capture: null };
|
|
20283
|
+
return {
|
|
20284
|
+
sessionExists: true,
|
|
20285
|
+
capture: mapWorkspaceCaptureRow({
|
|
20286
|
+
id: row.capture_id,
|
|
20287
|
+
session_id: row.capture_session_id,
|
|
20288
|
+
turn_id: row.capture_turn_id,
|
|
20289
|
+
revision: row.capture_revision,
|
|
20290
|
+
lease_epoch: row.capture_lease_epoch,
|
|
20291
|
+
state: row.capture_state,
|
|
20292
|
+
manifest_key: row.capture_manifest_key,
|
|
20293
|
+
tree_index_key: row.capture_tree_index_key,
|
|
20294
|
+
blob_keys: row.capture_blob_keys,
|
|
20295
|
+
size_bytes: row.capture_size_bytes,
|
|
20296
|
+
stats: row.capture_stats,
|
|
20297
|
+
captured_at: row.capture_captured_at
|
|
20298
|
+
})
|
|
20299
|
+
};
|
|
20300
|
+
});
|
|
20301
|
+
}
|
|
20249
20302
|
async function workspaceCaptureAtRevision(db, workspaceId, sessionId, revision) {
|
|
20250
20303
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
20251
20304
|
const rows = await scopedDb.execute(sql4`
|
|
@@ -22213,7 +22266,7 @@ async function materializeGoalContinuation(db, input) {
|
|
|
22213
22266
|
eq7(sessionSystemUpdates.workspaceId, input.workspaceId),
|
|
22214
22267
|
eq7(sessionSystemUpdates.sessionId, input.sessionId),
|
|
22215
22268
|
eq7(sessionSystemUpdates.kind, "agent_steer_instruction"),
|
|
22216
|
-
|
|
22269
|
+
eq7(sessionSystemUpdates.state, "pending")
|
|
22217
22270
|
)
|
|
22218
22271
|
).limit(1);
|
|
22219
22272
|
if (pendingSteer) {
|
|
@@ -22336,6 +22389,7 @@ async function materializeGoalContinuation(db, input) {
|
|
|
22336
22389
|
idempotencyKey: `agent_run.created:goal:${input.workspaceId}:${decision.goal.id}:${goalWakeRevision}`,
|
|
22337
22390
|
occurredAt: now
|
|
22338
22391
|
}).onConflictDoNothing({ target: usageEvents.idempotencyKey });
|
|
22392
|
+
const eventPreview = internalUpdateEventMember(update);
|
|
22339
22393
|
const insertedEvents = await tx.insert(sessionEvents).values([
|
|
22340
22394
|
{
|
|
22341
22395
|
accountId: session.accountId,
|
|
@@ -22344,11 +22398,13 @@ async function materializeGoalContinuation(db, input) {
|
|
|
22344
22398
|
sequence: session.lastSequence + 1,
|
|
22345
22399
|
type: "system.update.pending",
|
|
22346
22400
|
payload: sanitizeEventPayload({
|
|
22347
|
-
updateId:
|
|
22348
|
-
kind:
|
|
22349
|
-
classification:
|
|
22350
|
-
sourceId:
|
|
22351
|
-
|
|
22401
|
+
updateId: eventPreview.id,
|
|
22402
|
+
kind: eventPreview.kind,
|
|
22403
|
+
classification: eventPreview.classification,
|
|
22404
|
+
sourceId: eventPreview.sourceId,
|
|
22405
|
+
sourceIdTruncated: eventPreview.sourceIdTruncated,
|
|
22406
|
+
summary: eventPreview.summary,
|
|
22407
|
+
summaryTruncated: eventPreview.summaryTruncated
|
|
22352
22408
|
}),
|
|
22353
22409
|
occurredAt: now
|
|
22354
22410
|
},
|
|
@@ -22729,6 +22785,62 @@ async function enqueueSessionTurn(db, input) {
|
|
|
22729
22785
|
var MAX_INTERNAL_UPDATE_BYTES = 64 * 1024;
|
|
22730
22786
|
var MAX_INTERNAL_UPDATE_BATCH_MEMBERS = 100;
|
|
22731
22787
|
var MAX_INTERNAL_UPDATE_BATCH_BYTES = 256 * 1024;
|
|
22788
|
+
var MAX_INTERNAL_UPDATE_EVENT_SUMMARY_BYTES = 512;
|
|
22789
|
+
var MAX_INTERNAL_UPDATE_EVENT_SOURCE_BYTES = 256;
|
|
22790
|
+
function boundedInternalUpdateEventText(value, maxBytes) {
|
|
22791
|
+
if (Buffer.byteLength(value) <= maxBytes) return { text: value, truncated: false };
|
|
22792
|
+
const suffix = "\u2026";
|
|
22793
|
+
const bodyBudget = maxBytes - Buffer.byteLength(suffix);
|
|
22794
|
+
const bytes = Buffer.from(value);
|
|
22795
|
+
let text = bytes.subarray(0, bodyBudget).toString("utf8");
|
|
22796
|
+
if (text.endsWith("\uFFFD")) text = text.slice(0, -1);
|
|
22797
|
+
return { text: `${text}${suffix}`, truncated: true };
|
|
22798
|
+
}
|
|
22799
|
+
function internalUpdateEventMember(update) {
|
|
22800
|
+
const summary = boundedInternalUpdateEventText(
|
|
22801
|
+
update.summary,
|
|
22802
|
+
MAX_INTERNAL_UPDATE_EVENT_SUMMARY_BYTES
|
|
22803
|
+
);
|
|
22804
|
+
const source = boundedInternalUpdateEventText(
|
|
22805
|
+
update.sourceId,
|
|
22806
|
+
MAX_INTERNAL_UPDATE_EVENT_SOURCE_BYTES
|
|
22807
|
+
);
|
|
22808
|
+
return {
|
|
22809
|
+
id: update.id,
|
|
22810
|
+
kind: update.kind,
|
|
22811
|
+
classification: update.classification,
|
|
22812
|
+
sourceId: source.text,
|
|
22813
|
+
sourceIdTruncated: source.truncated,
|
|
22814
|
+
summary: summary.text,
|
|
22815
|
+
summaryTruncated: summary.truncated
|
|
22816
|
+
};
|
|
22817
|
+
}
|
|
22818
|
+
function selectBoundedSystemUpdateBatch(updates) {
|
|
22819
|
+
const selected = [];
|
|
22820
|
+
let selectedBytes = 0;
|
|
22821
|
+
for (const update of updates) {
|
|
22822
|
+
const updateBytes = Buffer.byteLength(
|
|
22823
|
+
JSON.stringify({
|
|
22824
|
+
id: update.id,
|
|
22825
|
+
kind: update.kind,
|
|
22826
|
+
classification: update.classification,
|
|
22827
|
+
sourceId: update.sourceId,
|
|
22828
|
+
summary: update.summary,
|
|
22829
|
+
payload: update.payload,
|
|
22830
|
+
lineage: update.lineage
|
|
22831
|
+
})
|
|
22832
|
+
);
|
|
22833
|
+
if (selected.length >= MAX_INTERNAL_UPDATE_BATCH_MEMBERS || // One individually large canonical input must still make progress. The
|
|
22834
|
+
// model/context boundary may reject it explicitly, but the queue cannot
|
|
22835
|
+
// wedge forever merely because the coalescing target is smaller.
|
|
22836
|
+
selected.length > 0 && selectedBytes + updateBytes > MAX_INTERNAL_UPDATE_BATCH_BYTES) {
|
|
22837
|
+
break;
|
|
22838
|
+
}
|
|
22839
|
+
selected.push(update);
|
|
22840
|
+
selectedBytes += updateBytes;
|
|
22841
|
+
}
|
|
22842
|
+
return selected;
|
|
22843
|
+
}
|
|
22732
22844
|
async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
22733
22845
|
const { sessionId, workflowId } = input;
|
|
22734
22846
|
return await withWorkspaceRls(
|
|
@@ -22740,29 +22852,18 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
22740
22852
|
and7(
|
|
22741
22853
|
eq7(sessionSystemUpdates.workspaceId, workspaceId),
|
|
22742
22854
|
eq7(sessionSystemUpdates.sessionId, sessionId),
|
|
22743
|
-
|
|
22855
|
+
eq7(sessionSystemUpdates.state, "pending"),
|
|
22744
22856
|
eq7(sessionSystemUpdates.kind, "agent_steer_instruction")
|
|
22745
22857
|
)
|
|
22746
22858
|
).orderBy(
|
|
22747
22859
|
desc2(sessionSystemUpdates.createdAt),
|
|
22748
22860
|
desc2(sessionSystemUpdates.id)
|
|
22749
22861
|
).limit(1).for("update");
|
|
22750
|
-
if (agentSteer) {
|
|
22751
|
-
await tx.update(sessionSystemUpdates).set({ state: "superseded" }).where(
|
|
22752
|
-
and7(
|
|
22753
|
-
eq7(sessionSystemUpdates.workspaceId, workspaceId),
|
|
22754
|
-
eq7(sessionSystemUpdates.sessionId, sessionId),
|
|
22755
|
-
eq7(sessionSystemUpdates.kind, "agent_steer_instruction"),
|
|
22756
|
-
inArray3(sessionSystemUpdates.state, ["pending", "deferred"]),
|
|
22757
|
-
ne(sessionSystemUpdates.id, agentSteer.id)
|
|
22758
|
-
)
|
|
22759
|
-
);
|
|
22760
|
-
}
|
|
22761
22862
|
const ordinary = await tx.select().from(sessionSystemUpdates).where(
|
|
22762
22863
|
and7(
|
|
22763
22864
|
eq7(sessionSystemUpdates.workspaceId, workspaceId),
|
|
22764
22865
|
eq7(sessionSystemUpdates.sessionId, sessionId),
|
|
22765
|
-
|
|
22866
|
+
eq7(sessionSystemUpdates.state, "pending"),
|
|
22766
22867
|
ne(sessionSystemUpdates.kind, "agent_steer_instruction")
|
|
22767
22868
|
)
|
|
22768
22869
|
).orderBy(
|
|
@@ -22775,12 +22876,15 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
22775
22876
|
count: 0,
|
|
22776
22877
|
lastSequence: nextSequence - 1,
|
|
22777
22878
|
triggerEventId: null,
|
|
22879
|
+
historyItemId: null,
|
|
22880
|
+
historyItem: null,
|
|
22778
22881
|
updates: [],
|
|
22882
|
+
events: [],
|
|
22779
22883
|
event: null
|
|
22780
22884
|
};
|
|
22781
22885
|
}
|
|
22782
|
-
const
|
|
22783
|
-
|
|
22886
|
+
const validUpdates = [];
|
|
22887
|
+
const cancelledUpdateIds = [];
|
|
22784
22888
|
for (const update of updates) {
|
|
22785
22889
|
const payload = update.payload;
|
|
22786
22890
|
if (payload.type === "goal_continuation") {
|
|
@@ -22798,38 +22902,56 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
22798
22902
|
).for("update").limit(1) : [];
|
|
22799
22903
|
if (!goal || goal.status !== "active" || goal.version !== goalVersion) {
|
|
22800
22904
|
await tx.update(sessionSystemUpdates).set({ state: "cancelled" }).where(eq7(sessionSystemUpdates.id, update.id));
|
|
22905
|
+
cancelledUpdateIds.push(update.id);
|
|
22801
22906
|
continue;
|
|
22802
22907
|
}
|
|
22803
22908
|
}
|
|
22804
|
-
|
|
22805
|
-
JSON.stringify({
|
|
22806
|
-
id: update.id,
|
|
22807
|
-
kind: update.kind,
|
|
22808
|
-
classification: update.classification,
|
|
22809
|
-
sourceId: update.sourceId,
|
|
22810
|
-
summary: update.summary,
|
|
22811
|
-
payload: update.payload,
|
|
22812
|
-
lineage: update.lineage
|
|
22813
|
-
})
|
|
22814
|
-
);
|
|
22815
|
-
if (deliverable.length >= MAX_INTERNAL_UPDATE_BATCH_MEMBERS || deliveredBytes + updateBytes > MAX_INTERNAL_UPDATE_BATCH_BYTES) {
|
|
22816
|
-
break;
|
|
22817
|
-
}
|
|
22818
|
-
deliverable.push(update);
|
|
22819
|
-
deliveredBytes += updateBytes;
|
|
22909
|
+
validUpdates.push(update);
|
|
22820
22910
|
}
|
|
22911
|
+
const deliverable = selectBoundedSystemUpdateBatch(validUpdates);
|
|
22821
22912
|
if (deliverable.length === 0) {
|
|
22913
|
+
const cancellationEvent = cancelledUpdateIds.length > 0 ? {
|
|
22914
|
+
accountId,
|
|
22915
|
+
workspaceId,
|
|
22916
|
+
sessionId,
|
|
22917
|
+
// No receiving turn exists when every candidate was
|
|
22918
|
+
// cancelled before a model batch could be persisted.
|
|
22919
|
+
turnId: null,
|
|
22920
|
+
turnGeneration: null,
|
|
22921
|
+
turnAttemptId: null,
|
|
22922
|
+
turnAssociation: null,
|
|
22923
|
+
sequence: nextSequence,
|
|
22924
|
+
type: "system.update.cancelled",
|
|
22925
|
+
payload: sanitizeEventPayload({
|
|
22926
|
+
updateIds: cancelledUpdateIds,
|
|
22927
|
+
count: cancelledUpdateIds.length,
|
|
22928
|
+
reason: "stale_goal_continuation"
|
|
22929
|
+
}),
|
|
22930
|
+
occurredAt
|
|
22931
|
+
} : null;
|
|
22822
22932
|
return {
|
|
22823
22933
|
count: 0,
|
|
22824
|
-
lastSequence: nextSequence - 1,
|
|
22934
|
+
lastSequence: cancellationEvent ? nextSequence : nextSequence - 1,
|
|
22825
22935
|
triggerEventId: null,
|
|
22936
|
+
historyItemId: null,
|
|
22937
|
+
historyItem: null,
|
|
22826
22938
|
updates: [],
|
|
22939
|
+
events: cancellationEvent ? [cancellationEvent] : [],
|
|
22827
22940
|
event: null
|
|
22828
22941
|
};
|
|
22829
22942
|
}
|
|
22943
|
+
const modelOrdered = [
|
|
22944
|
+
...deliverable.filter((update) => update.kind !== "agent_steer_instruction"),
|
|
22945
|
+
...deliverable.filter((update) => update.kind === "agent_steer_instruction")
|
|
22946
|
+
];
|
|
22947
|
+
const historyItemId = crypto.randomUUID();
|
|
22948
|
+
const historyItem = sessionSystemUpdateBatchHistoryItem(
|
|
22949
|
+
modelOrdered.map((update) => mapSessionSystemUpdate(update))
|
|
22950
|
+
);
|
|
22830
22951
|
await tx.update(sessionSystemUpdates).set({
|
|
22831
22952
|
state: "delivered",
|
|
22832
22953
|
deliveredTurnId: turnId,
|
|
22954
|
+
deliveredHistoryItemId: historyItemId,
|
|
22833
22955
|
deliveredAt: occurredAt
|
|
22834
22956
|
}).where(
|
|
22835
22957
|
and7(
|
|
@@ -22842,6 +22964,27 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
22842
22964
|
)
|
|
22843
22965
|
);
|
|
22844
22966
|
const eventId = triggerEventId ?? crypto.randomUUID();
|
|
22967
|
+
let sequence = nextSequence - 1;
|
|
22968
|
+
const events = [];
|
|
22969
|
+
if (cancelledUpdateIds.length > 0) {
|
|
22970
|
+
events.push({
|
|
22971
|
+
accountId,
|
|
22972
|
+
workspaceId,
|
|
22973
|
+
sessionId,
|
|
22974
|
+
turnId,
|
|
22975
|
+
turnGeneration,
|
|
22976
|
+
turnAttemptId: input.attemptId,
|
|
22977
|
+
turnAssociation: "current",
|
|
22978
|
+
sequence: ++sequence,
|
|
22979
|
+
type: "system.update.cancelled",
|
|
22980
|
+
payload: sanitizeEventPayload({
|
|
22981
|
+
updateIds: cancelledUpdateIds,
|
|
22982
|
+
count: cancelledUpdateIds.length,
|
|
22983
|
+
reason: "stale_goal_continuation"
|
|
22984
|
+
}),
|
|
22985
|
+
occurredAt
|
|
22986
|
+
});
|
|
22987
|
+
}
|
|
22845
22988
|
const event = {
|
|
22846
22989
|
id: eventId,
|
|
22847
22990
|
accountId,
|
|
@@ -22851,23 +22994,55 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
22851
22994
|
turnGeneration,
|
|
22852
22995
|
turnAttemptId: input.attemptId,
|
|
22853
22996
|
turnAssociation: "current",
|
|
22854
|
-
sequence:
|
|
22997
|
+
sequence: ++sequence,
|
|
22855
22998
|
type: "system.update.delivered",
|
|
22856
22999
|
payload: sanitizeEventPayload({
|
|
22857
23000
|
updateIds: deliverable.map((update) => update.id),
|
|
23001
|
+
historyItemId,
|
|
22858
23002
|
count: deliverable.length,
|
|
22859
|
-
classifications: [...new Set(deliverable.map((update) => update.classification))]
|
|
23003
|
+
classifications: [...new Set(deliverable.map((update) => update.classification))],
|
|
23004
|
+
members: modelOrdered.map(internalUpdateEventMember)
|
|
22860
23005
|
}),
|
|
22861
23006
|
occurredAt
|
|
22862
23007
|
};
|
|
23008
|
+
events.push(event);
|
|
22863
23009
|
return {
|
|
22864
23010
|
count: deliverable.length,
|
|
22865
|
-
lastSequence:
|
|
23011
|
+
lastSequence: sequence,
|
|
22866
23012
|
triggerEventId: eventId,
|
|
23013
|
+
historyItemId,
|
|
23014
|
+
historyItem,
|
|
22867
23015
|
updates: deliverable,
|
|
23016
|
+
events,
|
|
22868
23017
|
event
|
|
22869
23018
|
};
|
|
22870
23019
|
};
|
|
23020
|
+
const persistDeliveredUpdateBatch = async (delivered2, accountId, turnId) => {
|
|
23021
|
+
if (!delivered2.historyItemId || !delivered2.historyItem) {
|
|
23022
|
+
if (delivered2.count !== 0) {
|
|
23023
|
+
throw new Error("Delivered machine-input batch has no model-memory item");
|
|
23024
|
+
}
|
|
23025
|
+
return;
|
|
23026
|
+
}
|
|
23027
|
+
const [{ position } = { position: 0 }] = await tx.select({
|
|
23028
|
+
position: sql4`coalesce(max(${sessionHistoryItems.position}), -1) + 1`
|
|
23029
|
+
}).from(sessionHistoryItems).where(
|
|
23030
|
+
and7(
|
|
23031
|
+
eq7(sessionHistoryItems.workspaceId, workspaceId),
|
|
23032
|
+
eq7(sessionHistoryItems.sessionId, sessionId)
|
|
23033
|
+
)
|
|
23034
|
+
);
|
|
23035
|
+
await tx.insert(sessionHistoryItems).values({
|
|
23036
|
+
id: delivered2.historyItemId,
|
|
23037
|
+
accountId,
|
|
23038
|
+
workspaceId,
|
|
23039
|
+
sessionId,
|
|
23040
|
+
turnId,
|
|
23041
|
+
position: Number(position),
|
|
23042
|
+
item: sanitizeModelPayload(delivered2.historyItem),
|
|
23043
|
+
producerCodexCredentialId: null
|
|
23044
|
+
});
|
|
23045
|
+
};
|
|
22871
23046
|
const workspaceControl = await lockWorkspaceInferenceControl(
|
|
22872
23047
|
tx,
|
|
22873
23048
|
workspaceId,
|
|
@@ -23113,7 +23288,7 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
23113
23288
|
eq7(sessionSystemUpdates.workspaceId, workspaceId),
|
|
23114
23289
|
eq7(sessionSystemUpdates.sessionId, sessionId),
|
|
23115
23290
|
eq7(sessionSystemUpdates.kind, "agent_steer_instruction"),
|
|
23116
|
-
|
|
23291
|
+
eq7(sessionSystemUpdates.state, "pending")
|
|
23117
23292
|
)
|
|
23118
23293
|
).orderBy(
|
|
23119
23294
|
desc2(sessionSystemUpdates.createdAt),
|
|
@@ -23291,6 +23466,19 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
23291
23466
|
triggerEventId
|
|
23292
23467
|
);
|
|
23293
23468
|
if (delivered2.count === 0) {
|
|
23469
|
+
if (delivered2.events.length > 0) {
|
|
23470
|
+
await tx.insert(sessionEvents).values(delivered2.events);
|
|
23471
|
+
await tx.update(sessions).set({
|
|
23472
|
+
status: "idle",
|
|
23473
|
+
lastSequence: delivered2.lastSequence,
|
|
23474
|
+
updatedAt: now2
|
|
23475
|
+
}).where(
|
|
23476
|
+
and7(
|
|
23477
|
+
eq7(sessions.workspaceId, workspaceId),
|
|
23478
|
+
eq7(sessions.id, sessionId)
|
|
23479
|
+
)
|
|
23480
|
+
);
|
|
23481
|
+
}
|
|
23294
23482
|
return { action: "unclaimed", reason: "no-work" };
|
|
23295
23483
|
}
|
|
23296
23484
|
const goalUpdate = delivered2.updates.find(
|
|
@@ -23429,9 +23617,10 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
23429
23617
|
startedAt: now2
|
|
23430
23618
|
}).returning();
|
|
23431
23619
|
if (!internalTurn) throw new Error("Failed to create internal update inference");
|
|
23620
|
+
await persistDeliveredUpdateBatch(delivered2, session.accountId, internalTurn.id);
|
|
23432
23621
|
await registerAttempt(internalTurn);
|
|
23433
23622
|
if (!delivered2.event) throw new Error("Delivered update batch has no durable event");
|
|
23434
|
-
await tx.insert(sessionEvents).values(delivered2.
|
|
23623
|
+
await tx.insert(sessionEvents).values(delivered2.events);
|
|
23435
23624
|
if (goalUpdate && typeof goalUpdate.payload.goalId === "string") {
|
|
23436
23625
|
await tx.update(sessionGoals).set({ lastContinuationTurnId: internalTurn.id, updatedAt: now2 }).where(
|
|
23437
23626
|
and7(
|
|
@@ -23528,8 +23717,9 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
23528
23717
|
session.lastSequence + 1,
|
|
23529
23718
|
now
|
|
23530
23719
|
);
|
|
23531
|
-
|
|
23532
|
-
|
|
23720
|
+
await persistDeliveredUpdateBatch(delivered, session.accountId, row.id);
|
|
23721
|
+
if (delivered.events.length > 0) {
|
|
23722
|
+
await tx.insert(sessionEvents).values(delivered.events);
|
|
23533
23723
|
}
|
|
23534
23724
|
await tx.update(sessions).set({
|
|
23535
23725
|
status: "running",
|
|
@@ -23673,6 +23863,127 @@ async function markSessionAttemptQuiesced(db, input) {
|
|
|
23673
23863
|
return [mapEvent2(event)];
|
|
23674
23864
|
});
|
|
23675
23865
|
}
|
|
23866
|
+
async function getSessionAttemptActivityRef(db, input) {
|
|
23867
|
+
return await withRlsContext(
|
|
23868
|
+
db,
|
|
23869
|
+
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
23870
|
+
async (scopedDb) => {
|
|
23871
|
+
const [attempt] = await scopedDb.select({
|
|
23872
|
+
workflowId: sessionTurnAttempts.temporalWorkflowId,
|
|
23873
|
+
workflowRunId: sessionTurnAttempts.temporalWorkflowRunId,
|
|
23874
|
+
activityId: sessionTurnAttempts.temporalActivityId,
|
|
23875
|
+
quiescedAt: sessionTurnAttempts.quiescedAt
|
|
23876
|
+
}).from(sessionTurnAttempts).where(
|
|
23877
|
+
and7(
|
|
23878
|
+
eq7(sessionTurnAttempts.accountId, input.accountId),
|
|
23879
|
+
eq7(sessionTurnAttempts.workspaceId, input.workspaceId),
|
|
23880
|
+
eq7(sessionTurnAttempts.sessionId, input.sessionId),
|
|
23881
|
+
eq7(sessionTurnAttempts.id, input.attemptId),
|
|
23882
|
+
eq7(sessionTurnAttempts.temporalWorkflowId, input.temporalWorkflowId)
|
|
23883
|
+
)
|
|
23884
|
+
).limit(1);
|
|
23885
|
+
return attempt ? {
|
|
23886
|
+
workflowId: attempt.workflowId,
|
|
23887
|
+
workflowRunId: attempt.workflowRunId,
|
|
23888
|
+
activityId: attempt.activityId,
|
|
23889
|
+
quiesced: attempt.quiescedAt !== null
|
|
23890
|
+
} : null;
|
|
23891
|
+
}
|
|
23892
|
+
);
|
|
23893
|
+
}
|
|
23894
|
+
async function reconcileSessionAttemptQuiescence(db, input) {
|
|
23895
|
+
const eligibility = await withRlsContext(
|
|
23896
|
+
db,
|
|
23897
|
+
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
23898
|
+
async (scopedDb) => {
|
|
23899
|
+
const rows = await scopedDb.execute(sql4`
|
|
23900
|
+
select
|
|
23901
|
+
attempt.account_id,
|
|
23902
|
+
attempt.state,
|
|
23903
|
+
attempt.quiesced_at,
|
|
23904
|
+
attempt.temporal_workflow_id,
|
|
23905
|
+
attempt.temporal_workflow_run_id,
|
|
23906
|
+
attempt.temporal_activity_id,
|
|
23907
|
+
exists (
|
|
23908
|
+
select 1
|
|
23909
|
+
from session_attempt_interruptions interruption
|
|
23910
|
+
where interruption.workspace_id = attempt.workspace_id
|
|
23911
|
+
and interruption.session_id = attempt.session_id
|
|
23912
|
+
and interruption.attempt_id = attempt.id
|
|
23913
|
+
and interruption.state in ('settled', 'rejected_stale')
|
|
23914
|
+
) as interruption_settled,
|
|
23915
|
+
exists (
|
|
23916
|
+
select 1
|
|
23917
|
+
from session_attempt_interruptions interruption
|
|
23918
|
+
where interruption.workspace_id = attempt.workspace_id
|
|
23919
|
+
and interruption.session_id = attempt.session_id
|
|
23920
|
+
and interruption.attempt_id = attempt.id
|
|
23921
|
+
and interruption.state in ('pending', 'delivered', 'acknowledged')
|
|
23922
|
+
) as interruption_pending,
|
|
23923
|
+
(
|
|
23924
|
+
exists (
|
|
23925
|
+
select 1
|
|
23926
|
+
from sandbox_workspace_mutation_admissions admission
|
|
23927
|
+
where admission.account_id = attempt.account_id
|
|
23928
|
+
and admission.workspace_id = attempt.workspace_id
|
|
23929
|
+
and admission.session_id = attempt.session_id
|
|
23930
|
+
and admission.settled_at is null
|
|
23931
|
+
and (
|
|
23932
|
+
admission.attempt_id = attempt.id
|
|
23933
|
+
or (
|
|
23934
|
+
admission.actor_kind = 'process'
|
|
23935
|
+
and exists (
|
|
23936
|
+
select 1
|
|
23937
|
+
from sandbox_retained_processes process
|
|
23938
|
+
where process.account_id = attempt.account_id
|
|
23939
|
+
and process.workspace_id = attempt.workspace_id
|
|
23940
|
+
and process.session_id = attempt.session_id
|
|
23941
|
+
and process.id = admission.actor_id
|
|
23942
|
+
and process.owner_attempt_id = attempt.id
|
|
23943
|
+
)
|
|
23944
|
+
)
|
|
23945
|
+
)
|
|
23946
|
+
)
|
|
23947
|
+
or exists (
|
|
23948
|
+
select 1
|
|
23949
|
+
from sandbox_retained_processes process
|
|
23950
|
+
where process.account_id = attempt.account_id
|
|
23951
|
+
and process.workspace_id = attempt.workspace_id
|
|
23952
|
+
and process.session_id = attempt.session_id
|
|
23953
|
+
and process.owner_attempt_id = attempt.id
|
|
23954
|
+
and process.state = 'active'
|
|
23955
|
+
)
|
|
23956
|
+
) as writer_pending
|
|
23957
|
+
from session_turn_attempts attempt
|
|
23958
|
+
where attempt.account_id = ${input.accountId}
|
|
23959
|
+
and attempt.workspace_id = ${input.workspaceId}
|
|
23960
|
+
and attempt.session_id = ${input.sessionId}
|
|
23961
|
+
and attempt.id = ${input.attemptId}
|
|
23962
|
+
limit 1
|
|
23963
|
+
`);
|
|
23964
|
+
return rows[0] ?? null;
|
|
23965
|
+
}
|
|
23966
|
+
);
|
|
23967
|
+
if (!eligibility || eligibility.account_id !== input.accountId || eligibility.temporal_workflow_id !== input.temporalWorkflowId || eligibility.temporal_workflow_run_id !== input.temporalWorkflowRunId || eligibility.temporal_activity_id !== input.temporalActivityId || eligibility.state !== "closed" || !eligibility.interruption_settled || eligibility.interruption_pending) {
|
|
23968
|
+
return { action: "stale", events: [] };
|
|
23969
|
+
}
|
|
23970
|
+
if (eligibility.quiesced_at) {
|
|
23971
|
+
return { action: "quiesced", events: [] };
|
|
23972
|
+
}
|
|
23973
|
+
if (!input.activitySettled || eligibility.writer_pending) {
|
|
23974
|
+
return { action: "pending", events: [] };
|
|
23975
|
+
}
|
|
23976
|
+
const events = await markSessionAttemptQuiesced(db, {
|
|
23977
|
+
accountId: input.accountId,
|
|
23978
|
+
workspaceId: input.workspaceId,
|
|
23979
|
+
sessionId: input.sessionId,
|
|
23980
|
+
attemptId: input.attemptId,
|
|
23981
|
+
temporalWorkflowId: input.temporalWorkflowId,
|
|
23982
|
+
temporalWorkflowRunId: input.temporalWorkflowRunId,
|
|
23983
|
+
temporalActivityId: input.temporalActivityId
|
|
23984
|
+
});
|
|
23985
|
+
return { action: "quiesced", events };
|
|
23986
|
+
}
|
|
23676
23987
|
async function settleSessionAttemptInterruptions(db, workspaceId, sessionId, attemptId) {
|
|
23677
23988
|
return await withWorkspaceRls(
|
|
23678
23989
|
db,
|
|
@@ -23801,12 +24112,6 @@ async function settleSessionAttemptInterruptions(db, workspaceId, sessionId, att
|
|
|
23801
24112
|
outcome,
|
|
23802
24113
|
closedAt: now
|
|
23803
24114
|
});
|
|
23804
|
-
await requeueInterruptedSessionSystemUpdatesForTurnTx(
|
|
23805
|
-
tx,
|
|
23806
|
-
workspaceId,
|
|
23807
|
-
sessionId,
|
|
23808
|
-
turn.id
|
|
23809
|
-
);
|
|
23810
24115
|
const eventValues = steer ? [
|
|
23811
24116
|
{
|
|
23812
24117
|
accountId: session.accountId,
|
|
@@ -24676,10 +24981,36 @@ async function applySessionTurnSettlement(db, workspaceId, input) {
|
|
|
24676
24981
|
}
|
|
24677
24982
|
})
|
|
24678
24983
|
);
|
|
24984
|
+
const settledMachineInputs = ["completed", "failed", "cancelled", "superseded"].includes(
|
|
24985
|
+
input.turnStatus
|
|
24986
|
+
) ? await tx.select({
|
|
24987
|
+
id: sessionSystemUpdates.id,
|
|
24988
|
+
historyItemId: sessionSystemUpdates.deliveredHistoryItemId
|
|
24989
|
+
}).from(sessionSystemUpdates).where(
|
|
24990
|
+
and7(
|
|
24991
|
+
eq7(sessionSystemUpdates.workspaceId, workspaceId),
|
|
24992
|
+
eq7(sessionSystemUpdates.sessionId, input.sessionId),
|
|
24993
|
+
eq7(sessionSystemUpdates.deliveredTurnId, input.turnId),
|
|
24994
|
+
eq7(sessionSystemUpdates.state, "delivered")
|
|
24995
|
+
)
|
|
24996
|
+
).orderBy(
|
|
24997
|
+
asc4(sessionSystemUpdates.createdAt),
|
|
24998
|
+
asc4(sessionSystemUpdates.id)
|
|
24999
|
+
) : [];
|
|
25000
|
+
const machineInputSettlementEvent = settledMachineInputs.length > 0 ? {
|
|
25001
|
+
type: "system.update.settled",
|
|
25002
|
+
payload: {
|
|
25003
|
+
updateIds: settledMachineInputs.map((update) => update.id),
|
|
25004
|
+
count: settledMachineInputs.length,
|
|
25005
|
+
historyItemId: settledMachineInputs[0].historyItemId,
|
|
25006
|
+
outcome: input.turnStatus
|
|
25007
|
+
}
|
|
25008
|
+
} : null;
|
|
24679
25009
|
const settlementEvents = [
|
|
24680
25010
|
...recordingEvent ? [recordingEvent] : [],
|
|
24681
25011
|
...compactionRequestEvent ? [compactionRequestEvent] : [],
|
|
24682
25012
|
...terminalHumanInputEvents,
|
|
25013
|
+
...machineInputSettlementEvent ? [machineInputSettlementEvent] : [],
|
|
24683
25014
|
...input.events
|
|
24684
25015
|
];
|
|
24685
25016
|
const values = settlementEvents.map((event) => {
|
|
@@ -24735,21 +25066,6 @@ async function applySessionTurnSettlement(db, workspaceId, input) {
|
|
|
24735
25066
|
turn
|
|
24736
25067
|
);
|
|
24737
25068
|
}
|
|
24738
|
-
if (input.turnStatus === "failed") {
|
|
24739
|
-
await deferFailedSessionSystemUpdatesForTurnTx(
|
|
24740
|
-
tx,
|
|
24741
|
-
workspaceId,
|
|
24742
|
-
input.sessionId,
|
|
24743
|
-
input.turnId
|
|
24744
|
-
);
|
|
24745
|
-
} else if (["cancelled", "superseded"].includes(input.turnStatus)) {
|
|
24746
|
-
await requeueInterruptedSessionSystemUpdatesForTurnTx(
|
|
24747
|
-
tx,
|
|
24748
|
-
workspaceId,
|
|
24749
|
-
input.sessionId,
|
|
24750
|
-
input.turnId
|
|
24751
|
-
);
|
|
24752
|
-
}
|
|
24753
25069
|
await tx.update(sessions).set({
|
|
24754
25070
|
status: effectiveSessionStatus,
|
|
24755
25071
|
activeTurnId: input.activeTurnId,
|
|
@@ -24947,14 +25263,6 @@ async function settleCodexCredentialLeaseLoss(db, input) {
|
|
|
24947
25263
|
eq7(sessions.activeTurnId, input.turnId)
|
|
24948
25264
|
)
|
|
24949
25265
|
);
|
|
24950
|
-
if (!input.checkpointDurable) {
|
|
24951
|
-
await deferFailedSessionSystemUpdatesForTurnTx(
|
|
24952
|
-
tx,
|
|
24953
|
-
input.workspaceId,
|
|
24954
|
-
input.sessionId,
|
|
24955
|
-
input.turnId
|
|
24956
|
-
);
|
|
24957
|
-
}
|
|
24958
25266
|
await tx.execute(sql4`
|
|
24959
25267
|
delete from codex_credential_leases
|
|
24960
25268
|
where account_id = ${input.accountId}
|
|
@@ -25625,16 +25933,49 @@ async function getSessionQueueSnapshot(db, workspaceId, sessionId) {
|
|
|
25625
25933
|
inArray3(sessionTurns.source, ["user", "api"])
|
|
25626
25934
|
)
|
|
25627
25935
|
).orderBy(asc4(sessionTurns.position), asc4(sessionTurns.createdAt));
|
|
25936
|
+
const pendingInputs = await scopedDb.select().from(sessionSystemUpdates).where(
|
|
25937
|
+
and7(
|
|
25938
|
+
eq7(sessionSystemUpdates.workspaceId, workspaceId),
|
|
25939
|
+
eq7(sessionSystemUpdates.sessionId, sessionId),
|
|
25940
|
+
eq7(sessionSystemUpdates.state, "pending")
|
|
25941
|
+
)
|
|
25942
|
+
).orderBy(
|
|
25943
|
+
sql4`case when ${sessionSystemUpdates.kind} = 'agent_steer_instruction' then 0 else 1 end`,
|
|
25944
|
+
asc4(sessionSystemUpdates.createdAt),
|
|
25945
|
+
asc4(sessionSystemUpdates.id)
|
|
25946
|
+
);
|
|
25628
25947
|
const latestInterruption = await latestSessionAttemptInterruption(
|
|
25629
25948
|
scopedDb,
|
|
25630
25949
|
workspaceId,
|
|
25631
25950
|
sessionId
|
|
25632
25951
|
);
|
|
25952
|
+
const items = rows.map(mapSessionTurn);
|
|
25953
|
+
const nextInputBatch = selectBoundedSystemUpdateBatch(pendingInputs);
|
|
25954
|
+
const hasPendingAgentSteer = pendingInputs.some(
|
|
25955
|
+
(update) => update.kind === "agent_steer_instruction"
|
|
25956
|
+
);
|
|
25957
|
+
const attachmentTurn = hasPendingAgentSteer ? items.find((turn) => turn.metadata.delivery === "steer") : items[0];
|
|
25633
25958
|
return {
|
|
25634
25959
|
version: session.queueVersion,
|
|
25635
25960
|
effectiveControl: serializeEffectiveSessionControl(effectiveControl),
|
|
25636
25961
|
stoppingPreviousAttempt: latestInterruption !== null && latestInterruption.interruptionState !== "rejected_stale" && latestInterruption.quiescedAt === null,
|
|
25637
|
-
items
|
|
25962
|
+
items,
|
|
25963
|
+
pendingInputs: pendingInputs.map((update) => {
|
|
25964
|
+
const canonical = mapSessionSystemUpdate(update);
|
|
25965
|
+
return {
|
|
25966
|
+
id: canonical.id,
|
|
25967
|
+
sessionId: canonical.sessionId,
|
|
25968
|
+
kind: canonical.kind,
|
|
25969
|
+
classification: canonical.classification,
|
|
25970
|
+
sourceId: boundedInternalUpdateEventText(canonical.sourceId, 256).text,
|
|
25971
|
+
summary: boundedInternalUpdateEventText(canonical.summary, 512).text,
|
|
25972
|
+
createdAt: canonical.createdAt
|
|
25973
|
+
};
|
|
25974
|
+
}),
|
|
25975
|
+
pendingInputAttachment: attachmentTurn && nextInputBatch.length > 0 ? {
|
|
25976
|
+
turnId: attachmentTurn.id,
|
|
25977
|
+
inputIds: nextInputBatch.map((update) => update.id)
|
|
25978
|
+
} : null
|
|
25638
25979
|
};
|
|
25639
25980
|
});
|
|
25640
25981
|
}
|
|
@@ -25843,6 +26184,30 @@ async function markSessionWorkflowWakeDelivered(db, input) {
|
|
|
25843
26184
|
if (pendingAgentSteer) {
|
|
25844
26185
|
return { action: "pending_admission", blocker: "pending_agent_steer" };
|
|
25845
26186
|
}
|
|
26187
|
+
const [pendingQuiescence] = await tx.select({ id: sessionTurnAttempts.id }).from(sessionTurnAttempts).innerJoin(
|
|
26188
|
+
sessionAttemptInterruptions,
|
|
26189
|
+
and7(
|
|
26190
|
+
eq7(
|
|
26191
|
+
sessionAttemptInterruptions.workspaceId,
|
|
26192
|
+
sessionTurnAttempts.workspaceId
|
|
26193
|
+
),
|
|
26194
|
+
eq7(
|
|
26195
|
+
sessionAttemptInterruptions.sessionId,
|
|
26196
|
+
sessionTurnAttempts.sessionId
|
|
26197
|
+
),
|
|
26198
|
+
eq7(sessionAttemptInterruptions.attemptId, sessionTurnAttempts.id)
|
|
26199
|
+
)
|
|
26200
|
+
).where(
|
|
26201
|
+
and7(
|
|
26202
|
+
eq7(sessionTurnAttempts.workspaceId, input.workspaceId),
|
|
26203
|
+
eq7(sessionTurnAttempts.sessionId, input.sessionId),
|
|
26204
|
+
isNull2(sessionTurnAttempts.quiescedAt),
|
|
26205
|
+
inArray3(sessionAttemptInterruptions.state, ["settled", "rejected_stale"])
|
|
26206
|
+
)
|
|
26207
|
+
).limit(1);
|
|
26208
|
+
if (pendingQuiescence) {
|
|
26209
|
+
return { action: "pending_admission", blocker: "pending_quiescence" };
|
|
26210
|
+
}
|
|
25846
26211
|
}
|
|
25847
26212
|
const [row] = await tx.update(sessionWorkflowWakeOutbox).set({
|
|
25848
26213
|
deliveredRevision: sql4`greatest(${sessionWorkflowWakeOutbox.deliveredRevision}, ${input.wakeRevision})`,
|
|
@@ -25998,30 +26363,6 @@ async function addSessionSystemUpdate(db, input) {
|
|
|
25998
26363
|
}
|
|
25999
26364
|
return await addSessionSystemUpdateWithSourceMutation(db, input, async () => void 0);
|
|
26000
26365
|
}
|
|
26001
|
-
async function requeueInterruptedSessionSystemUpdatesForTurnTx(tx, workspaceId, sessionId, turnId) {
|
|
26002
|
-
await tx.update(sessionSystemUpdates).set({ state: "pending", deliveredTurnId: null, deliveredAt: null }).where(
|
|
26003
|
-
and7(
|
|
26004
|
-
eq7(sessionSystemUpdates.workspaceId, workspaceId),
|
|
26005
|
-
eq7(sessionSystemUpdates.sessionId, sessionId),
|
|
26006
|
-
eq7(sessionSystemUpdates.deliveredTurnId, turnId),
|
|
26007
|
-
eq7(sessionSystemUpdates.state, "delivered")
|
|
26008
|
-
)
|
|
26009
|
-
);
|
|
26010
|
-
}
|
|
26011
|
-
async function deferFailedSessionSystemUpdatesForTurnTx(tx, workspaceId, sessionId, turnId) {
|
|
26012
|
-
await tx.update(sessionSystemUpdates).set({
|
|
26013
|
-
state: sql4`case when ${sessionSystemUpdates.payload} ->> 'type' = 'goal_continuation' then 'failed' else 'deferred' end`,
|
|
26014
|
-
deliveredTurnId: null,
|
|
26015
|
-
deliveredAt: null
|
|
26016
|
-
}).where(
|
|
26017
|
-
and7(
|
|
26018
|
-
eq7(sessionSystemUpdates.workspaceId, workspaceId),
|
|
26019
|
-
eq7(sessionSystemUpdates.sessionId, sessionId),
|
|
26020
|
-
eq7(sessionSystemUpdates.deliveredTurnId, turnId),
|
|
26021
|
-
eq7(sessionSystemUpdates.state, "delivered")
|
|
26022
|
-
)
|
|
26023
|
-
);
|
|
26024
|
-
}
|
|
26025
26366
|
async function addSessionSystemUpdateWithSourceMutation(db, input, mutateSource) {
|
|
26026
26367
|
if (Buffer.byteLength(JSON.stringify(input.payload)) > MAX_INTERNAL_UPDATE_BYTES) {
|
|
26027
26368
|
throw new Error(`Internal update payload exceeds ${MAX_INTERNAL_UPDATE_BYTES} bytes`);
|
|
@@ -26100,6 +26441,7 @@ async function addSessionSystemUpdateWithSourceMutation(db, input, mutateSource)
|
|
|
26100
26441
|
};
|
|
26101
26442
|
}
|
|
26102
26443
|
const now = /* @__PURE__ */ new Date();
|
|
26444
|
+
const eventPreview = internalUpdateEventMember(inserted);
|
|
26103
26445
|
const [event] = await tx.insert(sessionEvents).values({
|
|
26104
26446
|
accountId: session.accountId,
|
|
26105
26447
|
workspaceId: input.workspaceId,
|
|
@@ -26107,11 +26449,13 @@ async function addSessionSystemUpdateWithSourceMutation(db, input, mutateSource)
|
|
|
26107
26449
|
sequence: session.lastSequence + 1,
|
|
26108
26450
|
type: "system.update.pending",
|
|
26109
26451
|
payload: sanitizeEventPayload({
|
|
26110
|
-
updateId:
|
|
26111
|
-
kind:
|
|
26112
|
-
classification:
|
|
26113
|
-
sourceId:
|
|
26114
|
-
|
|
26452
|
+
updateId: eventPreview.id,
|
|
26453
|
+
kind: eventPreview.kind,
|
|
26454
|
+
classification: eventPreview.classification,
|
|
26455
|
+
sourceId: eventPreview.sourceId,
|
|
26456
|
+
sourceIdTruncated: eventPreview.sourceIdTruncated,
|
|
26457
|
+
summary: eventPreview.summary,
|
|
26458
|
+
summaryTruncated: eventPreview.summaryTruncated
|
|
26115
26459
|
}),
|
|
26116
26460
|
occurredAt: now
|
|
26117
26461
|
}).returning();
|
|
@@ -26148,7 +26492,7 @@ async function listOutstandingSessionSystemUpdates(db, workspaceId, sessionId) {
|
|
|
26148
26492
|
and7(
|
|
26149
26493
|
eq7(sessionSystemUpdates.workspaceId, workspaceId),
|
|
26150
26494
|
eq7(sessionSystemUpdates.sessionId, sessionId),
|
|
26151
|
-
|
|
26495
|
+
eq7(sessionSystemUpdates.state, "pending")
|
|
26152
26496
|
)
|
|
26153
26497
|
).orderBy(asc4(sessionSystemUpdates.createdAt), asc4(sessionSystemUpdates.id));
|
|
26154
26498
|
return rows.map(mapSessionSystemUpdate);
|
|
@@ -26189,6 +26533,7 @@ function mapSessionSystemUpdate(row) {
|
|
|
26189
26533
|
lineage: row.lineage,
|
|
26190
26534
|
state: row.state,
|
|
26191
26535
|
deliveredTurnId: row.deliveredTurnId,
|
|
26536
|
+
deliveredHistoryItemId: row.deliveredHistoryItemId,
|
|
26192
26537
|
deliveredAt: row.deliveredAt?.toISOString() ?? null,
|
|
26193
26538
|
createdAt: row.createdAt.toISOString()
|
|
26194
26539
|
};
|
|
@@ -26732,6 +27077,7 @@ async function appendSessionEventsWithLockedSessionUpdate(db, workspaceId, sessi
|
|
|
26732
27077
|
lastSequence: sequence,
|
|
26733
27078
|
...update.resources !== void 0 ? { resources: update.resources } : {},
|
|
26734
27079
|
...update.tools !== void 0 ? { tools: update.tools } : {},
|
|
27080
|
+
...update.firstPartyMcpTools !== void 0 ? { firstPartyMcpTools: update.firstPartyMcpTools } : {},
|
|
26735
27081
|
...update.toolPolicy !== void 0 ? { toolPolicy: update.toolPolicy } : {},
|
|
26736
27082
|
...update.toolPolicyVersion !== void 0 ? { toolPolicyVersion: update.toolPolicyVersion } : {},
|
|
26737
27083
|
...update.model !== void 0 ? { model: update.model } : {},
|
|
@@ -26791,11 +27137,8 @@ function mapSession(row, effectiveControl, mcpServers = [], pin = mapSessionPin(
|
|
|
26791
27137
|
resources: row.resources,
|
|
26792
27138
|
skills: row.skills ?? [],
|
|
26793
27139
|
tools: row.tools,
|
|
26794
|
-
toolPolicy: row.toolPolicy
|
|
26795
|
-
|
|
26796
|
-
inheritedFromSessionId: null
|
|
26797
|
-
},
|
|
26798
|
-
toolPolicyVersion: Number(row.toolPolicyVersion ?? 1),
|
|
27140
|
+
toolPolicy: row.toolPolicy,
|
|
27141
|
+
toolPolicyVersion: Number(row.toolPolicyVersion),
|
|
26799
27142
|
metadata: row.metadata,
|
|
26800
27143
|
createdBy: initiatorFromStorage(
|
|
26801
27144
|
row.createdByKind,
|
|
@@ -26819,6 +27162,7 @@ function mapSession(row, effectiveControl, mcpServers = [], pin = mapSessionPin(
|
|
|
26819
27162
|
rigId: row.rigId ?? null,
|
|
26820
27163
|
rigVersionId: row.rigVersionId ?? null,
|
|
26821
27164
|
firstPartyMcpPermissions: row.firstPartyMcpPermissions ?? null,
|
|
27165
|
+
firstPartyMcpTools: row.firstPartyMcpTools,
|
|
26822
27166
|
mcpServers,
|
|
26823
27167
|
parentSessionId: row.parentSessionId ?? null,
|
|
26824
27168
|
rootSessionId: row.rootSessionId,
|
|
@@ -27764,6 +28108,7 @@ export {
|
|
|
27764
28108
|
getSandboxSessionEnvelope,
|
|
27765
28109
|
getScheduledTask,
|
|
27766
28110
|
getSession,
|
|
28111
|
+
getSessionAttemptActivityRef,
|
|
27767
28112
|
getSessionByCreateIdempotencyKey,
|
|
27768
28113
|
getSessionCodexState,
|
|
27769
28114
|
getSessionEvent,
|
|
@@ -27935,6 +28280,7 @@ export {
|
|
|
27935
28280
|
reapStaleLeaseHoldersGlobal,
|
|
27936
28281
|
reconcileCodexCapacityWait,
|
|
27937
28282
|
reconcileColdLostLeaseInstanceBlockers,
|
|
28283
|
+
reconcileSessionAttemptQuiescence,
|
|
27938
28284
|
recordAuditEvent,
|
|
27939
28285
|
recordCodexAccountConnectors,
|
|
27940
28286
|
recordCodexAccountUsage,
|
|
@@ -28012,6 +28358,7 @@ export {
|
|
|
28012
28358
|
sendAgentMessageInTransaction,
|
|
28013
28359
|
serializeEffectiveSessionControl,
|
|
28014
28360
|
sessionAuthorizationScopeFilter,
|
|
28361
|
+
sessionLatestWorkspaceCapture,
|
|
28015
28362
|
sessionSubject,
|
|
28016
28363
|
sessionTreeStatsForSessions,
|
|
28017
28364
|
sessionsWithActiveOpOnEnrollment,
|