@opengeni/db 0.28.1 → 0.31.1
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/attached-browser-devices.d.ts +42 -0
- package/dist/attempt-tool-catalogs.d.ts +16 -0
- package/dist/browser-auth.d.ts +91 -0
- package/dist/browser-identities.d.ts +128 -0
- package/dist/browser-sessions.d.ts +272 -0
- package/dist/browser-state-artifacts.d.ts +17 -0
- package/dist/capability-components.d.ts +37 -0
- package/dist/capability-integrations.d.ts +192 -0
- package/dist/chunk-F5FT7BEZ.js +3535 -0
- package/dist/chunk-F5FT7BEZ.js.map +1 -0
- package/dist/chunk-ISI2TIUG.js +639 -0
- package/dist/chunk-ISI2TIUG.js.map +1 -0
- package/dist/chunk-MWDVXQOL.js +11639 -0
- package/dist/chunk-MWDVXQOL.js.map +1 -0
- package/dist/chunk-NBE6CHRI.js +955 -0
- package/dist/chunk-NBE6CHRI.js.map +1 -0
- package/dist/{chunk-DBS5HPEW.js → chunk-YHZXQ7HP.js} +760 -11
- package/dist/chunk-YHZXQ7HP.js.map +1 -0
- package/dist/codemode-operations.d.ts +117 -0
- package/dist/codex-token-resolver.d.ts +2 -2
- package/dist/company-profile-schema.d.ts +798 -0
- package/dist/company-profile.d.ts +268 -0
- package/dist/computer-sessions.d.ts +109 -0
- package/dist/connection-token-resolver.d.ts +9 -4
- package/dist/database.d.ts +52 -3
- package/dist/editable-artifact-durable-export.d.ts +153 -0
- package/dist/editable-artifact-durable-export.js +788 -0
- package/dist/editable-artifact-durable-export.js.map +1 -0
- package/dist/editable-artifact-materialization.d.ts +123 -0
- package/dist/editable-artifacts-schema.d.ts +4152 -0
- package/dist/editable-artifacts.d.ts +610 -0
- package/dist/editable-artifacts.js +26 -0
- package/dist/editable-artifacts.js.map +1 -0
- package/dist/environment-crypto.d.ts +8 -4
- package/dist/generated-images.d.ts +139 -0
- package/dist/index.d.ts +958 -126
- package/dist/index.js +31204 -12172
- package/dist/index.js.map +1 -1
- package/dist/insights.d.ts +51 -4
- package/dist/integration-bindings.d.ts +70 -0
- package/dist/integration-features.d.ts +99 -0
- package/dist/interaction-revisions.d.ts +3 -0
- package/dist/interaction-schema.d.ts +5372 -0
- package/dist/knowledge-source-sync-schema.d.ts +1679 -0
- package/dist/knowledge-source-sync.d.ts +274 -0
- package/dist/lossless-columns.d.ts +58 -0
- package/dist/lossless-json.d.ts +39 -0
- package/dist/memory-domain.d.ts +3 -6
- package/dist/memory-governance.d.ts +2 -2
- package/dist/memory-slack-delivery.d.ts +101 -0
- package/dist/new-session-drafts.d.ts +2 -2
- package/dist/pack-components.d.ts +76 -0
- package/dist/pack-installations.d.ts +86 -0
- package/dist/persistence-errors.d.ts +7 -14
- package/dist/plugin-packages.d.ts +126 -0
- package/dist/preference-registry.d.ts +1 -1
- package/dist/provision-roles.d.ts +9 -1
- package/dist/provision-roles.js +1 -1
- package/dist/runtime-posture.d.ts +18 -6
- package/dist/schema.d.ts +19122 -8731
- package/dist/schema.js +173 -1
- package/dist/scoped-knowledge.d.ts +97 -1
- package/dist/session-control.d.ts +4 -4
- package/dist/session-queue-commands.d.ts +19 -11
- package/dist/session-realtime-context.d.ts +2 -2
- package/dist/session-realtime-ledger.d.ts +4 -4
- package/dist/session-realtime-mirror.d.ts +2 -2
- package/dist/session-realtime-state.d.ts +1 -1
- package/dist/session-realtime-terminal.d.ts +8 -1
- package/dist/session-realtime.d.ts +7 -7
- package/dist/session-tool-call-settlement.d.ts +1 -1
- package/dist/slack-user-link-access.d.ts +54 -0
- package/dist/transcription-recordings-schema.d.ts +44 -6
- package/dist/transcription-recordings.d.ts +3 -3
- package/dist/turn-initiator.d.ts +2 -2
- package/dist/video-generation.d.ts +216 -0
- package/dist/video-generation.js +66 -0
- package/dist/video-generation.js.map +1 -0
- package/dist/workspace-artifacts.d.ts +1 -1
- package/dist/workspace-instruction-policies.d.ts +1 -1
- package/dist/workspace-learning-policy-schema.d.ts +932 -0
- package/dist/workspace-learning-policy.d.ts +161 -0
- package/drizzle/0065_enrollment_credential_generation.sql +10 -0
- package/drizzle/0140_retained_screenshot_artifacts.sql +192 -0
- package/drizzle/0176_lossless_canonical_json.sql +975 -0
- package/drizzle/0177_session_events_workspace_turn_type_index.sql +5 -0
- package/drizzle/0178_permissioned_secret_reads.sql +14 -0
- package/drizzle/0179_slack_private_shortcut_delivery_gate.sql +85 -0
- package/drizzle/0180_retained_screenshot_lifecycle_fences.sql +273 -0
- package/drizzle/0181_connected_machine_removal.sql +52 -0
- package/drizzle/0182_connected_machine_remove_session_default.sql +77 -0
- package/drizzle/0183_model_call_provider_cost_estimates.sql +39 -0
- package/drizzle/0184_sandbox_drain_teardown_fence.sql +682 -0
- package/drizzle/0185_temporal_schedule_cleanup_outbox.sql +168 -0
- package/drizzle/0186_sandbox_capture_provider_contract.sql +400 -0
- package/drizzle/0187_generated_image_artifacts.sql +173 -0
- package/drizzle/0188_image_generation_retention_failure.sql +25 -0
- package/drizzle/0189_retained_session_image_formats.sql +13 -0
- package/drizzle/0190_timeline_annotations.sql +31 -0
- package/drizzle/0191_editable_artifact_engine.sql +3853 -0
- package/drizzle/0192_editable_artifact_live_tickets.sql +338 -0
- package/drizzle/0193_editable_artifact_authorization.sql +190 -0
- package/drizzle/0194_editable_artifact_durable_exports.sql +160 -0
- package/drizzle/0195_editable_artifact_import_authorization.sql +203 -0
- package/drizzle/0196_rig_provider_images.sql +152 -0
- package/drizzle/0197_knowledge_source_sync_schedules.sql +523 -0
- package/drizzle/0198_memory_slack_publication_delivery.sql +393 -0
- package/drizzle/0199_workspace_learning_policy.sql +980 -0
- package/drizzle/0201_company_profile_authority.sql +849 -0
- package/drizzle/0202_document_index_checkpoints.sql +85 -0
- package/drizzle/0203_durable_video_generation.sql +353 -0
- package/drizzle/0204_video_generation_funding.sql +44 -0
- package/drizzle/0205_attempt_tool_catalogs.sql +230 -0
- package/drizzle/0206_browser_sessions.sql +646 -0
- package/drizzle/0207_browser_identities.sql +379 -0
- package/drizzle/0208_attached_browser_devices.sql +165 -0
- package/drizzle/0209_computer_sessions.sql +575 -0
- package/drizzle/0210_browser_auth_network_interventions.sql +441 -0
- package/drizzle/0211_editable_artifact_session_links.sql +58 -0
- package/drizzle/0212_slack_installation_bindings.sql +348 -0
- package/drizzle/0213_slack_user_link_access_requests.sql +177 -0
- package/drizzle/0214_session_activity_commit_gate.sql +262 -0
- package/drizzle/0215_capabilities_platform.sql +980 -0
- package/drizzle/0216_pack_component_ownership.sql +235 -0
- package/drizzle/0217_capability_definition_delete_authority.sql +32 -0
- package/package.json +18 -5
- package/src/attached-browser-devices.ts +371 -0
- package/src/attempt-tool-catalogs.ts +131 -0
- package/src/browser-auth.ts +1896 -0
- package/src/browser-identities.ts +1168 -0
- package/src/browser-sessions.ts +2005 -0
- package/src/browser-state-artifacts.ts +59 -0
- package/src/capability-components.ts +166 -0
- package/src/capability-integrations.ts +1663 -0
- package/src/codemode-operations.ts +674 -0
- package/src/company-profile-schema.ts +143 -0
- package/src/company-profile.ts +968 -0
- package/src/computer-sessions.ts +1130 -0
- package/src/connection-token-resolver.ts +270 -25
- package/src/database.ts +434 -24
- package/src/editable-artifact-durable-export.ts +1201 -0
- package/src/editable-artifact-materialization.ts +893 -0
- package/src/editable-artifacts-schema.ts +879 -0
- package/src/editable-artifacts.ts +5404 -0
- package/src/environment-crypto.ts +22 -9
- package/src/generated-images.ts +740 -0
- package/src/index.ts +10117 -2730
- package/src/insights.ts +160 -13
- package/src/integration-bindings.ts +455 -0
- package/src/integration-features.ts +859 -0
- package/src/interaction-revisions.ts +40 -0
- package/src/interaction-schema.ts +1303 -0
- package/src/knowledge-source-sync-schema.ts +192 -0
- package/src/knowledge-source-sync.ts +1922 -0
- package/src/lossless-columns.ts +35 -0
- package/src/lossless-json.ts +322 -0
- package/src/memory-domain.ts +5 -44
- package/src/memory-slack-delivery.ts +801 -0
- package/src/pack-components.ts +954 -0
- package/src/pack-installations.ts +929 -0
- package/src/persistence-errors.ts +26 -34
- package/src/plugin-packages.ts +1186 -0
- package/src/provision-roles.ts +302 -1
- package/src/runtime-posture-cli.ts +9 -0
- package/src/runtime-posture.ts +514 -5
- package/src/schema.ts +5177 -2957
- package/src/scoped-knowledge-schema.ts +1 -1
- package/src/scoped-knowledge.ts +655 -3
- package/src/session-control.ts +133 -81
- package/src/session-queue-commands.ts +511 -247
- package/src/session-realtime-context.ts +20 -7
- package/src/session-realtime-ledger.ts +32 -10
- package/src/session-realtime-mirror.ts +4 -2
- package/src/session-realtime-terminal.ts +89 -21
- package/src/session-realtime.ts +10 -9
- package/src/session-tool-call-settlement.ts +38 -15
- package/src/slack-user-link-access.ts +702 -0
- package/src/transcription-recordings-schema.ts +5 -2
- package/src/transcription-recordings.ts +70 -40
- package/src/video-generation.ts +1452 -0
- package/src/workspace-learning-policy-schema.ts +139 -0
- package/src/workspace-learning-policy.ts +595 -0
- package/dist/chunk-DBS5HPEW.js.map +0 -1
- package/dist/chunk-HT5T62CC.js +0 -6803
- package/dist/chunk-HT5T62CC.js.map +0 -1
- package/dist/event-payload-sanitizer.d.ts +0 -32
- package/src/event-payload-sanitizer.ts +0 -377
|
@@ -3,7 +3,8 @@ import { createHash } from "node:crypto";
|
|
|
3
3
|
import { ReasoningEffort } from "@opengeni/contracts";
|
|
4
4
|
import { and, asc, desc, eq, inArray, isNull, sql } from "drizzle-orm";
|
|
5
5
|
|
|
6
|
-
import type { Database } from "./database";
|
|
6
|
+
import type { Database, SessionActivityDatabase } from "./database";
|
|
7
|
+
import { fromPostgresLosslessJson, fromPostgresLosslessText } from "./lossless-json";
|
|
7
8
|
import * as schema from "./schema";
|
|
8
9
|
import { submitHumanPromptInTransaction } from "./session-queue-commands";
|
|
9
10
|
|
|
@@ -177,7 +178,7 @@ function mapProjection(
|
|
|
177
178
|
* delegation into the same canonical Steer-or-start path used by a human.
|
|
178
179
|
*/
|
|
179
180
|
export async function flushSessionRealtimeTranscriptTailInTransaction(
|
|
180
|
-
db:
|
|
181
|
+
db: SessionActivityDatabase,
|
|
181
182
|
input: {
|
|
182
183
|
accountId: string;
|
|
183
184
|
workspaceId: string;
|
|
@@ -233,7 +234,9 @@ export async function flushSessionRealtimeTranscriptTailInTransaction(
|
|
|
233
234
|
sequence: schema.sessionRealtimeEntries.sequence,
|
|
234
235
|
role: schema.sessionRealtimeEntries.role,
|
|
235
236
|
text: schema.sessionRealtimeEntries.text,
|
|
237
|
+
textCodecVersion: schema.sessionRealtimeEntries.textCodecVersion,
|
|
236
238
|
payload: schema.sessionRealtimeEntries.payload,
|
|
239
|
+
payloadCodecVersion: schema.sessionRealtimeEntries.payloadCodecVersion,
|
|
237
240
|
})
|
|
238
241
|
.from(schema.sessionRealtimeEntries)
|
|
239
242
|
.where(
|
|
@@ -248,7 +251,12 @@ export async function flushSessionRealtimeTranscriptTailInTransaction(
|
|
|
248
251
|
),
|
|
249
252
|
)
|
|
250
253
|
.orderBy(asc(schema.sessionRealtimeEntries.sequence), asc(schema.sessionRealtimeEntries.id));
|
|
251
|
-
const
|
|
254
|
+
const decodedRows = rows.map((row) => ({
|
|
255
|
+
...row,
|
|
256
|
+
text: row.text === null ? null : fromPostgresLosslessText(row.text, row.textCodecVersion),
|
|
257
|
+
payload: fromPostgresLosslessJson(row.payload, row.payloadCodecVersion),
|
|
258
|
+
}));
|
|
259
|
+
const rendered = renderSessionRealtimeTail(decodedRows);
|
|
252
260
|
if (!rendered.context) return null;
|
|
253
261
|
|
|
254
262
|
const [session] = await db
|
|
@@ -290,7 +298,7 @@ export async function flushSessionRealtimeTranscriptTailInTransaction(
|
|
|
290
298
|
source: SESSION_REALTIME_TAIL_SOURCE,
|
|
291
299
|
realtimeId: mode.id,
|
|
292
300
|
lastDelegationItemId: latestDelegation?.delegationItemId ?? null,
|
|
293
|
-
sourceEntryIds:
|
|
301
|
+
sourceEntryIds: decodedRows.map((entry) => entry.id),
|
|
294
302
|
},
|
|
295
303
|
},
|
|
296
304
|
source: "api",
|
|
@@ -346,7 +354,9 @@ export async function listSessionRealtimeContinuityEntriesInTransaction(
|
|
|
346
354
|
sequence: schema.sessionRealtimeEntries.sequence,
|
|
347
355
|
role: schema.sessionRealtimeEntries.role,
|
|
348
356
|
text: schema.sessionRealtimeEntries.text,
|
|
357
|
+
textCodecVersion: schema.sessionRealtimeEntries.textCodecVersion,
|
|
349
358
|
payload: schema.sessionRealtimeEntries.payload,
|
|
359
|
+
payloadCodecVersion: schema.sessionRealtimeEntries.payloadCodecVersion,
|
|
350
360
|
createdAt: schema.sessionRealtimeEntries.createdAt,
|
|
351
361
|
modeStartedAt: schema.sessionRealtimeModes.startedAt,
|
|
352
362
|
})
|
|
@@ -371,10 +381,13 @@ export async function listSessionRealtimeContinuityEntriesInTransaction(
|
|
|
371
381
|
)
|
|
372
382
|
.limit(maximumEntries);
|
|
373
383
|
return rows.reverse().flatMap((row) => {
|
|
374
|
-
const
|
|
384
|
+
const text =
|
|
385
|
+
row.text === null ? null : fromPostgresLosslessText(row.text, row.textCodecVersion);
|
|
386
|
+
const payload = fromPostgresLosslessJson(row.payload, row.payloadCodecVersion);
|
|
387
|
+
const turnId = payload.turnId;
|
|
375
388
|
if (
|
|
376
389
|
(row.role !== "user" && row.role !== "assistant") ||
|
|
377
|
-
typeof
|
|
390
|
+
typeof text !== "string" ||
|
|
378
391
|
typeof turnId !== "string"
|
|
379
392
|
) {
|
|
380
393
|
return [];
|
|
@@ -384,7 +397,7 @@ export async function listSessionRealtimeContinuityEntriesInTransaction(
|
|
|
384
397
|
realtimeId: row.realtimeId,
|
|
385
398
|
sequence: row.sequence,
|
|
386
399
|
role: row.role,
|
|
387
|
-
text: takeUtf8Head(
|
|
400
|
+
text: takeUtf8Head(text, 16_000),
|
|
388
401
|
turnId,
|
|
389
402
|
createdAt: row.createdAt.toISOString(),
|
|
390
403
|
},
|
|
@@ -3,8 +3,12 @@ import { createHash } from "node:crypto";
|
|
|
3
3
|
import { LatencyMode, ReasoningEffort, type SessionRealtimeMode } from "@opengeni/contracts";
|
|
4
4
|
import { and, asc, desc, eq, inArray, isNull, or, sql } from "drizzle-orm";
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
6
|
+
import type { Database, SessionActivityDatabase } from "./database";
|
|
7
|
+
import {
|
|
8
|
+
fromPostgresLosslessJson,
|
|
9
|
+
fromPostgresLosslessText,
|
|
10
|
+
LOSSLESS_CONTENT_CODEC_VERSION,
|
|
11
|
+
} from "./lossless-json";
|
|
8
12
|
import * as schema from "./schema";
|
|
9
13
|
import {
|
|
10
14
|
assertSessionRealtimeOwnerInTransaction,
|
|
@@ -259,8 +263,8 @@ function mapEntry(row: EntryRow): SessionRealtimeLedgerEntry {
|
|
|
259
263
|
sourceUpdateId: row.sourceUpdateId,
|
|
260
264
|
historyItemId: row.historyItemId,
|
|
261
265
|
turnId: row.turnId,
|
|
262
|
-
text: row.text,
|
|
263
|
-
payload: row.payload,
|
|
266
|
+
text: row.text === null ? null : fromPostgresLosslessText(row.text, row.textCodecVersion),
|
|
267
|
+
payload: fromPostgresLosslessJson(row.payload, row.payloadCodecVersion),
|
|
264
268
|
clientAckedAt: row.clientAckedAt?.toISOString() ?? null,
|
|
265
269
|
providerAckedAt: row.providerAckedAt?.toISOString() ?? null,
|
|
266
270
|
createdAt: row.createdAt.toISOString(),
|
|
@@ -288,7 +292,7 @@ function assertBoundedString(
|
|
|
288
292
|
}
|
|
289
293
|
|
|
290
294
|
function boundedPayload(input: Record<string, unknown> | undefined): Record<string, unknown> {
|
|
291
|
-
const payload =
|
|
295
|
+
const payload = input ?? {};
|
|
292
296
|
if (
|
|
293
297
|
Buffer.byteLength(JSON.stringify(payload), "utf8") > SESSION_REALTIME_LEDGER_MAX_PAYLOAD_BYTES
|
|
294
298
|
) {
|
|
@@ -1019,6 +1023,9 @@ function inboundReplayMatches(
|
|
|
1019
1023
|
text: string | null,
|
|
1020
1024
|
payload: Record<string, unknown>,
|
|
1021
1025
|
): boolean {
|
|
1026
|
+
const storedText =
|
|
1027
|
+
row.text === null ? null : fromPostgresLosslessText(row.text, row.textCodecVersion);
|
|
1028
|
+
const storedPayload = fromPostgresLosslessJson(row.payload, row.payloadCodecVersion);
|
|
1022
1029
|
return (
|
|
1023
1030
|
row.direction === "provider_in" &&
|
|
1024
1031
|
row.kind === input.kind &&
|
|
@@ -1026,8 +1033,9 @@ function inboundReplayMatches(
|
|
|
1026
1033
|
row.providerEventId === (input.providerEventId ?? null) &&
|
|
1027
1034
|
row.delegationItemId === (input.delegationItemId ?? null) &&
|
|
1028
1035
|
row.sourceUpdateId === null &&
|
|
1029
|
-
|
|
1030
|
-
JSON.stringify(canonicalJsonValue(
|
|
1036
|
+
storedText === text &&
|
|
1037
|
+
JSON.stringify(canonicalJsonValue(storedPayload)) ===
|
|
1038
|
+
JSON.stringify(canonicalJsonValue(payload))
|
|
1031
1039
|
);
|
|
1032
1040
|
}
|
|
1033
1041
|
|
|
@@ -1055,17 +1063,19 @@ async function appendInvalidDelegationFailure(
|
|
|
1055
1063
|
kind: "error",
|
|
1056
1064
|
delegationItemId: incoming.delegationItemId ?? null,
|
|
1057
1065
|
text: failure.message,
|
|
1066
|
+
textCodecVersion: LOSSLESS_CONTENT_CODEC_VERSION,
|
|
1058
1067
|
payload: {
|
|
1059
1068
|
code: failure.code,
|
|
1060
1069
|
callOperationId: incoming.operationId,
|
|
1061
1070
|
},
|
|
1071
|
+
payloadCodecVersion: LOSSLESS_CONTENT_CODEC_VERSION,
|
|
1062
1072
|
createdAt: now,
|
|
1063
1073
|
updatedAt: now,
|
|
1064
1074
|
});
|
|
1065
1075
|
}
|
|
1066
1076
|
|
|
1067
1077
|
async function admitRealtimeDelegationInTransaction(
|
|
1068
|
-
db:
|
|
1078
|
+
db: SessionActivityDatabase,
|
|
1069
1079
|
input: Pick<
|
|
1070
1080
|
SyncSessionRealtimeLedgerInput,
|
|
1071
1081
|
"workspaceId" | "sessionId" | "realtimeId" | "connectionEpoch" | "ownerSubjectId"
|
|
@@ -1189,7 +1199,11 @@ async function materializeRealtimeUpdates(
|
|
|
1189
1199
|
)
|
|
1190
1200
|
.orderBy(asc(schema.sessionSystemUpdates.createdAt), asc(schema.sessionSystemUpdates.id))
|
|
1191
1201
|
.limit(SESSION_REALTIME_LEDGER_MAX_OUTBOUND);
|
|
1192
|
-
const updates = rows.map(({ update }) =>
|
|
1202
|
+
const updates = rows.map(({ update }) => ({
|
|
1203
|
+
...update,
|
|
1204
|
+
summary: fromPostgresLosslessText(update.summary, update.summaryCodecVersion),
|
|
1205
|
+
payload: fromPostgresLosslessJson(update.payload, update.payloadCodecVersion),
|
|
1206
|
+
}));
|
|
1193
1207
|
if (updates.length === 0) return;
|
|
1194
1208
|
await db.insert(schema.sessionRealtimeEntries).values(
|
|
1195
1209
|
updates.map((update) => ({
|
|
@@ -1204,6 +1218,7 @@ async function materializeRealtimeUpdates(
|
|
|
1204
1218
|
kind: "session_update",
|
|
1205
1219
|
sourceUpdateId: update.id,
|
|
1206
1220
|
text: update.summary,
|
|
1221
|
+
textCodecVersion: LOSSLESS_CONTENT_CODEC_VERSION,
|
|
1207
1222
|
payload: boundedPayload({
|
|
1208
1223
|
updateId: update.id,
|
|
1209
1224
|
kind: update.kind,
|
|
@@ -1213,6 +1228,7 @@ async function materializeRealtimeUpdates(
|
|
|
1213
1228
|
payload: update.payload,
|
|
1214
1229
|
lineage: update.lineage,
|
|
1215
1230
|
}),
|
|
1231
|
+
payloadCodecVersion: LOSSLESS_CONTENT_CODEC_VERSION,
|
|
1216
1232
|
createdAt: now,
|
|
1217
1233
|
updatedAt: now,
|
|
1218
1234
|
})),
|
|
@@ -1252,7 +1268,7 @@ function assertProviderAckSequences(values: number[] | undefined, maximum: numbe
|
|
|
1252
1268
|
}
|
|
1253
1269
|
|
|
1254
1270
|
export async function syncSessionRealtimeLedgerInTransaction(
|
|
1255
|
-
db:
|
|
1271
|
+
db: SessionActivityDatabase,
|
|
1256
1272
|
input: SyncSessionRealtimeLedgerInput,
|
|
1257
1273
|
hooks: SyncSessionRealtimeLedgerHooks = {},
|
|
1258
1274
|
): Promise<SyncSessionRealtimeLedgerResult> {
|
|
@@ -1404,7 +1420,9 @@ export async function syncSessionRealtimeLedgerInTransaction(
|
|
|
1404
1420
|
delegationItemId: incoming.delegationItemId ?? null,
|
|
1405
1421
|
historyItemId: null,
|
|
1406
1422
|
text,
|
|
1423
|
+
textCodecVersion: LOSSLESS_CONTENT_CODEC_VERSION,
|
|
1407
1424
|
payload,
|
|
1425
|
+
payloadCodecVersion: LOSSLESS_CONTENT_CODEC_VERSION,
|
|
1408
1426
|
createdAt: now,
|
|
1409
1427
|
updatedAt: now,
|
|
1410
1428
|
})
|
|
@@ -1612,7 +1630,9 @@ export async function appendSessionRealtimeOutboundInTransaction(
|
|
|
1612
1630
|
kind: input.kind,
|
|
1613
1631
|
delegationItemId: input.delegationItemId,
|
|
1614
1632
|
text,
|
|
1633
|
+
textCodecVersion: LOSSLESS_CONTENT_CODEC_VERSION,
|
|
1615
1634
|
payload,
|
|
1635
|
+
payloadCodecVersion: LOSSLESS_CONTENT_CODEC_VERSION,
|
|
1616
1636
|
createdAt: now,
|
|
1617
1637
|
updatedAt: now,
|
|
1618
1638
|
})
|
|
@@ -1757,6 +1777,7 @@ export async function projectSessionRealtimeDelegationProgressInTransaction(
|
|
|
1757
1777
|
delegationItemId: call.delegationItemId,
|
|
1758
1778
|
turnId: input.turnId,
|
|
1759
1779
|
text: chunk,
|
|
1780
|
+
textCodecVersion: LOSSLESS_CONTENT_CODEC_VERSION,
|
|
1760
1781
|
payload: boundedPayload({
|
|
1761
1782
|
route: "delegation_context",
|
|
1762
1783
|
channel: "commentary",
|
|
@@ -1772,6 +1793,7 @@ export async function projectSessionRealtimeDelegationProgressInTransaction(
|
|
|
1772
1793
|
chunkIndex,
|
|
1773
1794
|
chunkCount: chunks.length,
|
|
1774
1795
|
}),
|
|
1796
|
+
payloadCodecVersion: LOSSLESS_CONTENT_CODEC_VERSION,
|
|
1775
1797
|
createdAt: now,
|
|
1776
1798
|
updatedAt: now,
|
|
1777
1799
|
})),
|
|
@@ -3,8 +3,8 @@ import { createHash } from "node:crypto";
|
|
|
3
3
|
import type { HumanInputQuestion, HumanInputResponse } from "@opengeni/contracts";
|
|
4
4
|
import { and, desc, eq, gt, sql } from "drizzle-orm";
|
|
5
5
|
|
|
6
|
-
import { sanitizeEventPayload } from "./event-payload-sanitizer";
|
|
7
6
|
import type { Database } from "./database";
|
|
7
|
+
import { LOSSLESS_CONTENT_CODEC_VERSION } from "./lossless-json";
|
|
8
8
|
import * as schema from "./schema";
|
|
9
9
|
|
|
10
10
|
const SESSION_REALTIME_MIRROR_MAX_TEXT_BYTES = 131_072;
|
|
@@ -59,7 +59,7 @@ function boundedText(value: string): string {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
function boundedPayload(value: Record<string, unknown>): Record<string, unknown> {
|
|
62
|
-
const payload =
|
|
62
|
+
const payload = value;
|
|
63
63
|
if (
|
|
64
64
|
Buffer.byteLength(JSON.stringify(payload), "utf8") > SESSION_REALTIME_MIRROR_MAX_PAYLOAD_BYTES
|
|
65
65
|
) {
|
|
@@ -137,7 +137,9 @@ export async function mirrorSessionRealtimeContextInTransaction(
|
|
|
137
137
|
direction: "provider_out",
|
|
138
138
|
kind: "session_update",
|
|
139
139
|
text: boundedText(input.text),
|
|
140
|
+
textCodecVersion: LOSSLESS_CONTENT_CODEC_VERSION,
|
|
140
141
|
payload,
|
|
142
|
+
payloadCodecVersion: LOSSLESS_CONTENT_CODEC_VERSION,
|
|
141
143
|
createdAt: now,
|
|
142
144
|
updatedAt: now,
|
|
143
145
|
})
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
|
|
3
|
+
import {
|
|
4
|
+
retainedOutputUnavailable,
|
|
5
|
+
validateRetainedOutputEvidence,
|
|
6
|
+
type RetainedOutputEvidence,
|
|
7
|
+
} from "@opengeni/contracts";
|
|
3
8
|
import { and, eq, inArray, sql } from "drizzle-orm";
|
|
4
9
|
|
|
5
|
-
import { sanitizeEventPayload } from "./event-payload-sanitizer";
|
|
6
10
|
import type { Database } from "./database";
|
|
11
|
+
import {
|
|
12
|
+
fromPostgresLosslessJson,
|
|
13
|
+
fromPostgresLosslessText,
|
|
14
|
+
LOSSLESS_CONTENT_CODEC_VERSION,
|
|
15
|
+
} from "./lossless-json";
|
|
7
16
|
import { mirrorSessionRealtimeContextInTransaction } from "./session-realtime-mirror";
|
|
8
17
|
import * as schema from "./schema";
|
|
9
18
|
|
|
@@ -17,9 +26,11 @@ export type ProjectSessionRealtimeDelegationTerminalInput = {
|
|
|
17
26
|
turnId: string;
|
|
18
27
|
turnStatus: "completed" | "failed" | "cancelled" | "superseded";
|
|
19
28
|
terminalEvent: {
|
|
29
|
+
id: string | null;
|
|
20
30
|
type: "turn.completed" | "turn.failed" | "turn.cancelled" | "turn.superseded";
|
|
21
31
|
payload: Record<string, unknown>;
|
|
22
32
|
};
|
|
33
|
+
retainedOutputEvidence?: unknown;
|
|
23
34
|
now?: Date;
|
|
24
35
|
};
|
|
25
36
|
|
|
@@ -71,20 +82,48 @@ function deterministicTerminalOperationId(turnId: string): string {
|
|
|
71
82
|
}
|
|
72
83
|
|
|
73
84
|
function boundedPayload(input: Record<string, unknown> | undefined): Record<string, unknown> {
|
|
74
|
-
const payload =
|
|
85
|
+
const payload = input ?? {};
|
|
75
86
|
if (Buffer.byteLength(JSON.stringify(payload), "utf8") > MAX_PAYLOAD_BYTES) {
|
|
76
87
|
throw new Error("Realtime payload exceeds the durable ledger limit");
|
|
77
88
|
}
|
|
78
89
|
return payload;
|
|
79
90
|
}
|
|
80
91
|
|
|
81
|
-
function
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
92
|
+
function payloadBytes(value: Record<string, unknown>): number {
|
|
93
|
+
return Buffer.byteLength(JSON.stringify(value), "utf8");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function fitsRealtimePayload(value: Record<string, unknown>): boolean {
|
|
97
|
+
return payloadBytes(value) <= MAX_PAYLOAD_BYTES;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function retainedEvidence(value: unknown): RetainedOutputEvidence {
|
|
101
|
+
return validateRetainedOutputEvidence(value) ?? retainedOutputUnavailable();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function terminalReference(
|
|
105
|
+
input: ProjectSessionRealtimeDelegationTerminalInput,
|
|
106
|
+
terminal: Record<string, unknown>,
|
|
107
|
+
): Record<string, unknown> {
|
|
108
|
+
const output = typeof terminal.output === "string" ? terminal.output : null;
|
|
109
|
+
return {
|
|
110
|
+
canonicalEvent: {
|
|
111
|
+
id: input.terminalEvent.id,
|
|
112
|
+
type: input.terminalEvent.type,
|
|
113
|
+
},
|
|
114
|
+
truncation: {
|
|
115
|
+
truncated: true,
|
|
116
|
+
reason: "realtime_ledger_limit",
|
|
117
|
+
originalBytes: payloadBytes(terminal),
|
|
118
|
+
outputBytes: output === null ? null : Buffer.byteLength(output, "utf8"),
|
|
119
|
+
fullEvidence: retainedEvidence(input.retainedOutputEvidence),
|
|
120
|
+
},
|
|
121
|
+
};
|
|
85
122
|
}
|
|
86
123
|
|
|
87
|
-
function
|
|
124
|
+
export function buildSessionRealtimeDelegationTerminalProjection(
|
|
125
|
+
input: ProjectSessionRealtimeDelegationTerminalInput,
|
|
126
|
+
): {
|
|
88
127
|
kind: "delegation_result" | "error";
|
|
89
128
|
text: string;
|
|
90
129
|
payload: Record<string, unknown>;
|
|
@@ -95,19 +134,33 @@ function terminalProjection(input: ProjectSessionRealtimeDelegationTerminalInput
|
|
|
95
134
|
`Realtime delegation terminal event ${input.terminalEvent.type} does not match ${input.turnStatus}`,
|
|
96
135
|
);
|
|
97
136
|
}
|
|
98
|
-
const terminal =
|
|
137
|
+
const terminal = input.terminalEvent.payload;
|
|
99
138
|
if (input.turnStatus === "completed") {
|
|
100
139
|
const output =
|
|
101
140
|
typeof terminal.output === "string" ? terminal.output : "Delegated turn completed.";
|
|
102
|
-
|
|
141
|
+
const exactPayload = {
|
|
142
|
+
status: input.turnStatus,
|
|
143
|
+
turnId: input.turnId,
|
|
144
|
+
terminalEventId: input.terminalEvent.id,
|
|
145
|
+
terminalEventType: input.terminalEvent.type,
|
|
146
|
+
terminal,
|
|
147
|
+
};
|
|
148
|
+
if (Buffer.byteLength(output, "utf8") <= MAX_TEXT_BYTES && fitsRealtimePayload(exactPayload)) {
|
|
149
|
+
return {
|
|
150
|
+
kind: "delegation_result",
|
|
151
|
+
text: output,
|
|
152
|
+
payload: exactPayload,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
103
155
|
return {
|
|
104
156
|
kind: "delegation_result",
|
|
105
|
-
text:
|
|
157
|
+
text: "Delegated turn completed. The full result remains in the canonical session event.",
|
|
106
158
|
payload: boundedPayload({
|
|
107
159
|
status: input.turnStatus,
|
|
108
160
|
turnId: input.turnId,
|
|
161
|
+
terminalEventId: input.terminalEvent.id,
|
|
109
162
|
terminalEventType: input.terminalEvent.type,
|
|
110
|
-
terminal,
|
|
163
|
+
terminal: terminalReference(input, terminal),
|
|
111
164
|
}),
|
|
112
165
|
};
|
|
113
166
|
}
|
|
@@ -119,16 +172,31 @@ function terminalProjection(input: ProjectSessionRealtimeDelegationTerminalInput
|
|
|
119
172
|
typeof terminal.error === "string" && terminal.error.length > 0
|
|
120
173
|
? terminal.error
|
|
121
174
|
: `Delegated turn ${input.turnStatus}.`;
|
|
122
|
-
|
|
175
|
+
const exactPayload = {
|
|
176
|
+
code,
|
|
177
|
+
status: input.turnStatus,
|
|
178
|
+
turnId: input.turnId,
|
|
179
|
+
terminalEventId: input.terminalEvent.id,
|
|
180
|
+
terminalEventType: input.terminalEvent.type,
|
|
181
|
+
terminal,
|
|
182
|
+
};
|
|
183
|
+
if (Buffer.byteLength(message, "utf8") <= MAX_TEXT_BYTES && fitsRealtimePayload(exactPayload)) {
|
|
184
|
+
return {
|
|
185
|
+
kind: "error",
|
|
186
|
+
text: message,
|
|
187
|
+
payload: exactPayload,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
123
190
|
return {
|
|
124
191
|
kind: "error",
|
|
125
|
-
text:
|
|
192
|
+
text: `Delegated turn ${input.turnStatus}. The full diagnostic remains in the canonical session event.`,
|
|
126
193
|
payload: boundedPayload({
|
|
127
|
-
code,
|
|
194
|
+
...(Buffer.byteLength(code, "utf8") <= 256 ? { code } : {}),
|
|
128
195
|
status: input.turnStatus,
|
|
129
196
|
turnId: input.turnId,
|
|
197
|
+
terminalEventId: input.terminalEvent.id,
|
|
130
198
|
terminalEventType: input.terminalEvent.type,
|
|
131
|
-
terminal,
|
|
199
|
+
terminal: terminalReference(input, terminal),
|
|
132
200
|
}),
|
|
133
201
|
};
|
|
134
202
|
}
|
|
@@ -150,8 +218,8 @@ function mapEntry(
|
|
|
150
218
|
sourceUpdateId: row.sourceUpdateId,
|
|
151
219
|
historyItemId: row.historyItemId,
|
|
152
220
|
turnId: row.turnId,
|
|
153
|
-
text: row.text,
|
|
154
|
-
payload: row.payload,
|
|
221
|
+
text: row.text === null ? null : fromPostgresLosslessText(row.text, row.textCodecVersion),
|
|
222
|
+
payload: fromPostgresLosslessJson(row.payload, row.payloadCodecVersion),
|
|
155
223
|
clientAckedAt: row.clientAckedAt?.toISOString() ?? null,
|
|
156
224
|
providerAckedAt: row.providerAckedAt?.toISOString() ?? null,
|
|
157
225
|
createdAt: row.createdAt.toISOString(),
|
|
@@ -187,7 +255,7 @@ export async function projectSessionRealtimeDelegationTerminalInTransaction(
|
|
|
187
255
|
if (calls.length > 1) {
|
|
188
256
|
throw new Error(`Delegation turn ${input.turnId} has multiple accepted realtime calls`);
|
|
189
257
|
}
|
|
190
|
-
const projected =
|
|
258
|
+
const projected = buildSessionRealtimeDelegationTerminalProjection(input);
|
|
191
259
|
const now = input.now ?? new Date();
|
|
192
260
|
const call = calls[0] ?? null;
|
|
193
261
|
const [mode] = call
|
|
@@ -225,10 +293,8 @@ export async function projectSessionRealtimeDelegationTerminalInTransaction(
|
|
|
225
293
|
channel: "speakable",
|
|
226
294
|
text: projected.text,
|
|
227
295
|
payload: {
|
|
296
|
+
...projected.payload,
|
|
228
297
|
route: "session_context",
|
|
229
|
-
status: input.turnStatus,
|
|
230
|
-
terminalEventType: input.terminalEvent.type,
|
|
231
|
-
terminal: boundedPayload(input.terminalEvent.payload),
|
|
232
298
|
...(call ? { priorRealtimeId: call.realtimeId } : {}),
|
|
233
299
|
},
|
|
234
300
|
now,
|
|
@@ -296,7 +362,9 @@ export async function projectSessionRealtimeDelegationTerminalInTransaction(
|
|
|
296
362
|
delegationItemId: call.delegationItemId,
|
|
297
363
|
turnId: input.turnId,
|
|
298
364
|
text: projected.text,
|
|
365
|
+
textCodecVersion: LOSSLESS_CONTENT_CODEC_VERSION,
|
|
299
366
|
payload,
|
|
367
|
+
payloadCodecVersion: LOSSLESS_CONTENT_CODEC_VERSION,
|
|
300
368
|
createdAt: now,
|
|
301
369
|
updatedAt: now,
|
|
302
370
|
})
|
package/src/session-realtime.ts
CHANGED
|
@@ -8,8 +8,8 @@ import type {
|
|
|
8
8
|
} from "@opengeni/contracts";
|
|
9
9
|
import { and, asc, eq, gt, inArray, isNull, or } from "drizzle-orm";
|
|
10
10
|
|
|
11
|
-
import {
|
|
12
|
-
import
|
|
11
|
+
import type { Database, SessionActivityDatabase } from "./database";
|
|
12
|
+
import { LOSSLESS_CONTENT_CODEC_VERSION } from "./lossless-json";
|
|
13
13
|
import { flushSessionRealtimeTranscriptTailInTransaction } from "./session-realtime-context";
|
|
14
14
|
import {
|
|
15
15
|
evaluateSessionControl,
|
|
@@ -161,7 +161,7 @@ function assertOwner(
|
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
async function appendRealtimeLifecycleEvent(
|
|
164
|
-
db:
|
|
164
|
+
db: SessionActivityDatabase,
|
|
165
165
|
session: SessionRow,
|
|
166
166
|
sequence: number,
|
|
167
167
|
type: Extract<SessionEventType, "session.realtime.started" | "session.realtime.ended">,
|
|
@@ -185,7 +185,8 @@ async function appendRealtimeLifecycleEvent(
|
|
|
185
185
|
sessionId: session.id,
|
|
186
186
|
sequence,
|
|
187
187
|
type,
|
|
188
|
-
payload:
|
|
188
|
+
payload: payload,
|
|
189
|
+
payloadCodecVersion: LOSSLESS_CONTENT_CODEC_VERSION,
|
|
189
190
|
occurredAt: now,
|
|
190
191
|
})
|
|
191
192
|
.returning();
|
|
@@ -258,7 +259,7 @@ async function registerNormalModeWake(db: Database, session: SessionRow, reason:
|
|
|
258
259
|
}
|
|
259
260
|
|
|
260
261
|
async function endWithEvent(
|
|
261
|
-
db:
|
|
262
|
+
db: SessionActivityDatabase,
|
|
262
263
|
session: SessionRow,
|
|
263
264
|
row: RealtimeRow,
|
|
264
265
|
reason: SessionRealtimeEndReason,
|
|
@@ -351,7 +352,7 @@ function assertRealtimeAdmission(session: SessionRow): void {
|
|
|
351
352
|
}
|
|
352
353
|
|
|
353
354
|
export async function beginSessionRealtimeInTransaction(
|
|
354
|
-
db:
|
|
355
|
+
db: SessionActivityDatabase,
|
|
355
356
|
input: BeginSessionRealtimeInput,
|
|
356
357
|
): Promise<SessionRealtimeMutationResult> {
|
|
357
358
|
const now = input.now ?? new Date();
|
|
@@ -552,7 +553,7 @@ export async function assertSessionRealtimeOwnerInTransaction(
|
|
|
552
553
|
}
|
|
553
554
|
|
|
554
555
|
export async function renewSessionRealtimeInTransaction(
|
|
555
|
-
db:
|
|
556
|
+
db: SessionActivityDatabase,
|
|
556
557
|
input: RenewSessionRealtimeInput,
|
|
557
558
|
): Promise<RenewSessionRealtimeResult> {
|
|
558
559
|
const now = input.now ?? new Date();
|
|
@@ -615,7 +616,7 @@ export async function renewSessionRealtimeInTransaction(
|
|
|
615
616
|
}
|
|
616
617
|
|
|
617
618
|
export async function endSessionRealtimeInTransaction(
|
|
618
|
-
db:
|
|
619
|
+
db: SessionActivityDatabase,
|
|
619
620
|
input: EndSessionRealtimeInput,
|
|
620
621
|
): Promise<SessionRealtimeMutationResult> {
|
|
621
622
|
const now = input.now ?? new Date();
|
|
@@ -648,7 +649,7 @@ export async function endSessionRealtimeInTransaction(
|
|
|
648
649
|
|
|
649
650
|
/** Lazily settle an expired voice lease under the canonical session lock. */
|
|
650
651
|
export async function settleExpiredSessionRealtimeInTransaction(
|
|
651
|
-
db:
|
|
652
|
+
db: SessionActivityDatabase,
|
|
652
653
|
session: SessionRow,
|
|
653
654
|
now = new Date(),
|
|
654
655
|
): Promise<SessionRow> {
|
|
@@ -2,8 +2,9 @@ import type { SessionEvent } from "@opengeni/contracts";
|
|
|
2
2
|
import { boundModelToolOutputItem } from "@opengeni/codex";
|
|
3
3
|
import { and, asc, eq, sql } from "drizzle-orm";
|
|
4
4
|
import type { Database } from "./database";
|
|
5
|
-
import {
|
|
5
|
+
import { fromPostgresLosslessJson, LOSSLESS_CONTENT_CODEC_VERSION } from "./lossless-json";
|
|
6
6
|
import * as schema from "./schema";
|
|
7
|
+
import { cancelUnacceptedVideoGenerationsForToolCallsInTransaction } from "./video-generation";
|
|
7
8
|
|
|
8
9
|
export const TOOL_RESULT_TYPE_BY_CALL_TYPE: Readonly<Record<string, string>> = {
|
|
9
10
|
function_call: "function_call_result",
|
|
@@ -93,7 +94,7 @@ function mapEvent(row: typeof schema.sessionEvents.$inferSelect): SessionEvent {
|
|
|
93
94
|
sessionId: row.sessionId,
|
|
94
95
|
sequence: row.sequence,
|
|
95
96
|
type: row.type as SessionEvent["type"],
|
|
96
|
-
payload: row.payload,
|
|
97
|
+
payload: fromPostgresLosslessJson(row.payload, row.payloadCodecVersion),
|
|
97
98
|
occurredAt: row.occurredAt.toISOString(),
|
|
98
99
|
clientEventId: row.clientEventId,
|
|
99
100
|
turnId: row.turnId,
|
|
@@ -115,7 +116,7 @@ export async function closePendingSessionToolCallsInTransaction(
|
|
|
115
116
|
tx: Database,
|
|
116
117
|
input: ClosePendingSessionToolCallsInput,
|
|
117
118
|
): Promise<{ sequence: number; events: SessionEvent[]; closed: number }> {
|
|
118
|
-
const
|
|
119
|
+
const pendingRows = await tx
|
|
119
120
|
.select()
|
|
120
121
|
.from(schema.sessionPendingToolCalls)
|
|
121
122
|
.where(
|
|
@@ -127,12 +128,21 @@ export async function closePendingSessionToolCallsInTransaction(
|
|
|
127
128
|
)
|
|
128
129
|
.orderBy(asc(schema.sessionPendingToolCalls.createdAt), asc(schema.sessionPendingToolCalls.id))
|
|
129
130
|
.for("update");
|
|
131
|
+
const pending = pendingRows.map((row) => ({
|
|
132
|
+
...row,
|
|
133
|
+
callItem: fromPostgresLosslessJson(row.callItem, row.callItemCodecVersion),
|
|
134
|
+
resultItem:
|
|
135
|
+
row.resultItem === null
|
|
136
|
+
? null
|
|
137
|
+
: fromPostgresLosslessJson(row.resultItem, row.resultItemCodecVersion),
|
|
138
|
+
}));
|
|
130
139
|
if (pending.length === 0) return { sequence: input.sequence, events: [], closed: 0 };
|
|
131
140
|
|
|
132
141
|
const history = await tx
|
|
133
142
|
.select({
|
|
134
143
|
position: schema.sessionHistoryItems.position,
|
|
135
144
|
item: schema.sessionHistoryItems.item,
|
|
145
|
+
itemCodecVersion: schema.sessionHistoryItems.itemCodecVersion,
|
|
136
146
|
active: schema.sessionHistoryItems.active,
|
|
137
147
|
})
|
|
138
148
|
.from(schema.sessionHistoryItems)
|
|
@@ -144,6 +154,10 @@ export async function closePendingSessionToolCallsInTransaction(
|
|
|
144
154
|
),
|
|
145
155
|
)
|
|
146
156
|
.orderBy(asc(schema.sessionHistoryItems.position));
|
|
157
|
+
const decodedHistory = history.map((row) => ({
|
|
158
|
+
...row,
|
|
159
|
+
item: fromPostgresLosslessJson(row.item, row.itemCodecVersion),
|
|
160
|
+
}));
|
|
147
161
|
const [{ maxPosition } = { maxPosition: -1 }] = await tx
|
|
148
162
|
.select({ maxPosition: sql<number>`coalesce(max(${schema.sessionHistoryItems.position}), -1)` })
|
|
149
163
|
.from(schema.sessionHistoryItems)
|
|
@@ -173,23 +187,23 @@ export async function closePendingSessionToolCallsInTransaction(
|
|
|
173
187
|
const eventValues: Array<typeof schema.sessionEvents.$inferInsert> = [];
|
|
174
188
|
const resolutions = pending.map((call) => {
|
|
175
189
|
const resultType = TOOL_RESULT_TYPE_BY_CALL_TYPE[call.callType];
|
|
176
|
-
const existingCall =
|
|
190
|
+
const existingCall = decodedHistory.find(
|
|
177
191
|
({ item }) => historyItemType(item) === call.callType && historyCallId(item) === call.callId,
|
|
178
192
|
);
|
|
179
193
|
const existingResult = resultType
|
|
180
|
-
?
|
|
194
|
+
? decodedHistory.find(
|
|
181
195
|
({ item, position }) =>
|
|
182
196
|
position > (existingCall?.position ?? Number.MAX_SAFE_INTEGER) &&
|
|
183
197
|
historyItemType(item) === resultType &&
|
|
184
198
|
historyCallId(item) === call.callId,
|
|
185
199
|
)
|
|
186
200
|
: undefined;
|
|
187
|
-
const activeCall =
|
|
201
|
+
const activeCall = decodedHistory.find(
|
|
188
202
|
({ item, active }) =>
|
|
189
203
|
active && historyItemType(item) === call.callType && historyCallId(item) === call.callId,
|
|
190
204
|
);
|
|
191
205
|
const activeResult = resultType
|
|
192
|
-
?
|
|
206
|
+
? decodedHistory.find(
|
|
193
207
|
({ item, active, position }) =>
|
|
194
208
|
active &&
|
|
195
209
|
position > (activeCall?.position ?? Number.MAX_SAFE_INTEGER) &&
|
|
@@ -232,7 +246,8 @@ export async function closePendingSessionToolCallsInTransaction(
|
|
|
232
246
|
sessionId: input.sessionId,
|
|
233
247
|
turnId: input.turnId,
|
|
234
248
|
position: nextPosition++,
|
|
235
|
-
item:
|
|
249
|
+
item: resolution.call.callItem,
|
|
250
|
+
itemCodecVersion: LOSSLESS_CONTENT_CODEC_VERSION,
|
|
236
251
|
active: true,
|
|
237
252
|
});
|
|
238
253
|
}
|
|
@@ -255,12 +270,11 @@ export async function closePendingSessionToolCallsInTransaction(
|
|
|
255
270
|
sessionId: input.sessionId,
|
|
256
271
|
turnId: input.turnId,
|
|
257
272
|
position: nextPosition++,
|
|
258
|
-
item:
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
resolution.call.modelToolOutputTruncationTokens ?? undefined,
|
|
262
|
-
),
|
|
273
|
+
item: boundModelToolOutputItem(
|
|
274
|
+
resolution.result,
|
|
275
|
+
resolution.call.modelToolOutputTruncationTokens ?? undefined,
|
|
263
276
|
),
|
|
277
|
+
itemCodecVersion: LOSSLESS_CONTENT_CODEC_VERSION,
|
|
264
278
|
active: true,
|
|
265
279
|
});
|
|
266
280
|
}
|
|
@@ -280,7 +294,7 @@ export async function closePendingSessionToolCallsInTransaction(
|
|
|
280
294
|
turnGeneration: resolution.call.executionGeneration,
|
|
281
295
|
turnAttemptId: resolution.call.attemptId,
|
|
282
296
|
turnAssociation: "current",
|
|
283
|
-
payload:
|
|
297
|
+
payload: {
|
|
284
298
|
id: resolution.call.callId,
|
|
285
299
|
output: resolution.interrupted
|
|
286
300
|
? {
|
|
@@ -302,7 +316,8 @@ export async function closePendingSessionToolCallsInTransaction(
|
|
|
302
316
|
unsupportedCallShape:
|
|
303
317
|
resolution.interrupted && (!resolution.result || !resolution.rawCallIsValid),
|
|
304
318
|
},
|
|
305
|
-
}
|
|
319
|
+
},
|
|
320
|
+
payloadCodecVersion: LOSSLESS_CONTENT_CODEC_VERSION,
|
|
306
321
|
occurredAt: input.now,
|
|
307
322
|
});
|
|
308
323
|
}
|
|
@@ -312,6 +327,14 @@ export async function closePendingSessionToolCallsInTransaction(
|
|
|
312
327
|
eventValues.length > 0
|
|
313
328
|
? await tx.insert(schema.sessionEvents).values(eventValues).returning()
|
|
314
329
|
: [];
|
|
330
|
+
await cancelUnacceptedVideoGenerationsForToolCallsInTransaction(tx, {
|
|
331
|
+
workspaceId: input.workspaceId,
|
|
332
|
+
sessionId: input.sessionId,
|
|
333
|
+
turnId: input.turnId,
|
|
334
|
+
toolCallIds: pending.map((call) => call.callId),
|
|
335
|
+
reason: input.reason,
|
|
336
|
+
now: input.now,
|
|
337
|
+
});
|
|
315
338
|
await tx
|
|
316
339
|
.delete(schema.sessionPendingToolCalls)
|
|
317
340
|
.where(
|