@opengeni/worker-bundle 0.27.0-canary.1 → 0.27.2-canary.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.
Files changed (60) hide show
  1. package/dist/activities/agent-turn/agent-build.d.ts +3 -4
  2. package/dist/activities/agent-turn/governance-model.d.ts +2 -3
  3. package/dist/activities/agent-turn/skill-checkout.d.ts +21 -0
  4. package/dist/activities/agent-turn/skill-install.d.ts +12 -0
  5. package/dist/activities/agent-turn/skill-read.d.ts +15 -0
  6. package/dist/activities/agent-turn/skill-save.d.ts +26 -0
  7. package/dist/activities/agent-turn/skill-search.d.ts +16 -0
  8. package/dist/activities/agent-turn/skill-selection.d.ts +17 -0
  9. package/dist/activities/agent-turn/skill-tools.d.ts +20 -0
  10. package/dist/activities/agent-turn/skill-transfer.d.ts +26 -0
  11. package/dist/activities/agent-turn/tool-environment.d.ts +7 -0
  12. package/dist/activities/parent-wake.d.ts +12 -2
  13. package/dist/activities/run-input.d.ts +11 -5
  14. package/dist/activities/sandbox-lease.d.ts +5 -4
  15. package/dist/activities/types.d.ts +4 -2
  16. package/dist/activities/workflow-wake.d.ts +2 -4
  17. package/dist/{activities-control-VMA3XMHE.js → activities-control-WZRFEIJH.js} +103 -26
  18. package/dist/activities-control-WZRFEIJH.js.map +1 -0
  19. package/dist/{activities-turn-57AOUNYN.js → activities-turn-V7J34ZOF.js} +945 -532
  20. package/dist/activities-turn-V7J34ZOF.js.map +1 -0
  21. package/dist/{chunk-D4ZEFOYH.js → chunk-BARTLVBK.js} +1 -1
  22. package/dist/chunk-BARTLVBK.js.map +1 -0
  23. package/dist/{chunk-7LS42PHP.js → chunk-C54VDT6I.js} +590 -34
  24. package/dist/chunk-C54VDT6I.js.map +1 -0
  25. package/dist/index.js +6 -4
  26. package/dist/index.js.map +1 -1
  27. package/dist/model-context-contributions.d.ts +2 -0
  28. package/dist/observability-metrics.d.ts +1 -1
  29. package/dist/workflow-bundle.js +1 -1
  30. package/package.json +17 -17
  31. package/src/activities/agent-turn/agent-build.ts +8 -34
  32. package/src/activities/agent-turn/errors.ts +4 -0
  33. package/src/activities/agent-turn/governance-model.ts +15 -19
  34. package/src/activities/agent-turn/run.ts +4 -6
  35. package/src/activities/agent-turn/sandbox-provision.ts +9 -0
  36. package/src/activities/agent-turn/skill-checkout.ts +124 -0
  37. package/src/activities/agent-turn/skill-install.ts +57 -0
  38. package/src/activities/agent-turn/skill-read.ts +117 -0
  39. package/src/activities/agent-turn/skill-save.ts +124 -0
  40. package/src/activities/agent-turn/skill-search.ts +110 -0
  41. package/src/activities/agent-turn/skill-selection.ts +53 -0
  42. package/src/activities/agent-turn/skill-tools.ts +268 -0
  43. package/src/activities/agent-turn/skill-transfer.ts +137 -0
  44. package/src/activities/agent-turn/tool-environment.ts +93 -1
  45. package/src/activities/automations.ts +3 -1
  46. package/src/activities/context-compaction.ts +26 -2
  47. package/src/activities/parent-wake.ts +66 -5
  48. package/src/activities/run-input.ts +88 -12
  49. package/src/activities/sandbox-lease.ts +77 -20
  50. package/src/activities/scheduled-tasks.ts +2 -0
  51. package/src/activities/types.ts +4 -2
  52. package/src/activities/workflow-wake.ts +42 -5
  53. package/src/index.ts +3 -1
  54. package/src/model-context-contributions.ts +18 -2
  55. package/src/observability-metrics.ts +2 -0
  56. package/src/sandbox-routing.ts +42 -1
  57. package/dist/activities-control-VMA3XMHE.js.map +0 -1
  58. package/dist/activities-turn-57AOUNYN.js.map +0 -1
  59. package/dist/chunk-7LS42PHP.js.map +0 -1
  60. package/dist/chunk-D4ZEFOYH.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  observabilityEventLogger
3
- } from "./chunk-D4ZEFOYH.js";
3
+ } from "./chunk-BARTLVBK.js";
4
4
 
5
5
  // src/activity-services.ts
6
6
  import { dbSearchPath, getSettings, resolveNatsControlPlaneAuth } from "@opengeni/config";
@@ -1433,31 +1433,6 @@ async function resolveWorkspacePackRuntime(db, workspaceId) {
1433
1433
  if (packs.length === 0) return emptyPackRuntime;
1434
1434
  return workspacePackRuntimeFromPacks(packs);
1435
1435
  }
1436
- async function resolveWorkspaceInstalledSkillRuntime(db, workspaceId) {
1437
- const installedSkills = await listInstalledPortableSkills(db, workspaceId);
1438
- const activations = [];
1439
- for (const installed of installedSkills) {
1440
- const artifact = buildPortableSkillArtifact(installed.files);
1441
- if (artifact.name !== installed.name || artifact.description !== installed.description || artifact.contentSha256 !== installed.contentSha256) {
1442
- throw new Error(
1443
- `Installed Skill artifact verification failed for ${installed.capabilityId}; reinstall it from the pinned source`
1444
- );
1445
- }
1446
- activations.push({
1447
- source: "installation",
1448
- id: installed.capabilityId,
1449
- artifact: {
1450
- name: artifact.name,
1451
- description: artifact.description,
1452
- files: artifact.files.map((file) => ({ path: file.path, content: file.content }))
1453
- },
1454
- version: installed.version,
1455
- contentSha256: artifact.contentSha256,
1456
- reason: installed.source === "library" ? "installed from the curated Skill library" : installed.source === "pack" ? "installed as a Pack-owned Skill" : `installed from ${installed.sourceUrl}`
1457
- });
1458
- }
1459
- return { activations };
1460
- }
1461
1436
  function workspacePackRuntimeFromPacks(packs) {
1462
1437
  const sandboxRuntime = legacySandboxRuntimeFromPacks(packs);
1463
1438
  const skillActivations = [];
@@ -1776,6 +1751,10 @@ async function deleteWorkspaceArchiveObjectKeys(objectStorage, keys) {
1776
1751
 
1777
1752
  // src/sandbox-routing.ts
1778
1753
  import { sandboxLifecycleTransitionWaitMs as sandboxLifecycleTransitionWaitMs2 } from "@opengeni/config";
1754
+ import {
1755
+ createProviderCommandRetainer,
1756
+ retainedProviderCommandPersistence
1757
+ } from "@opengeni/db/retained-provider-commands";
1779
1758
  import {
1780
1759
  adoptConnectedMachineSessionBackgroundCommand,
1781
1760
  adoptManagedSessionBackgroundCommand,
@@ -3036,6 +3015,14 @@ async function waitForWarm(services, ids) {
3036
3015
  }
3037
3016
 
3038
3017
  // src/sandbox-routing.ts
3018
+ var retainWorkspaceProviderCommand = createProviderCommandRetainer(
3019
+ retainWorkspaceMutationProcess,
3020
+ (error) => error instanceof SandboxRetainedProcessPromotionFencedError ? error.process : null
3021
+ );
3022
+ function admittedCommandHandle(value) {
3023
+ if (!value || typeof value !== "object") return void 0;
3024
+ return value.admission?.workspaceGeneration;
3025
+ }
3039
3026
  function relayConfigFromSettings(settings) {
3040
3027
  const raw = settings.selfhostedRelayUrl?.trim();
3041
3028
  if (!raw) {
@@ -3205,12 +3192,13 @@ function afterPersistableHomeMutation(services, ids, home) {
3205
3192
  }
3206
3193
  if (outcome === "resolved" && retainedProcess) {
3207
3194
  try {
3208
- await retainWorkspaceMutationProcess(services.db, {
3195
+ await retainWorkspaceProviderCommand(services.db, {
3209
3196
  accountId: fence.accountId,
3210
3197
  workspaceId: ids.workspaceId,
3211
3198
  sessionId: ids.sessionId,
3212
3199
  processId: retainedProcess.id,
3213
3200
  providerSessionId: retainedProcess.providerSessionId,
3201
+ ...retainedProcess.providerCommand ? { providerCommand: retainedProcess.providerCommand } : {},
3214
3202
  admissionId: exactAdmission.id,
3215
3203
  admittedWorkspaceGeneration: exactAdmission.workspaceGeneration,
3216
3204
  operation: op,
@@ -3571,6 +3559,15 @@ function wrapTurnBoxWithRouting(services, ids, established) {
3571
3559
  },
3572
3560
  resolveActiveBackend: resolver,
3573
3561
  ...services.onSandboxOperation ? { onOperation: services.onSandboxOperation } : {},
3562
+ providerCommandHandle: admittedCommandHandle,
3563
+ ...ids.workspaceMutationFence ? {
3564
+ providerCommandPersistence: (process) => retainedProviderCommandPersistence(db, {
3565
+ accountId: ids.workspaceMutationFence.accountId,
3566
+ workspaceId: ids.workspaceId,
3567
+ sessionId: ids.sessionId,
3568
+ processId: process.id
3569
+ })
3570
+ } : {},
3574
3571
  ...beforeMutation ? { beforeMutation } : {},
3575
3572
  ...afterMutation ? { afterMutation } : {},
3576
3573
  ...beforeProcessMutation ? { beforeProcessMutation } : {},
@@ -3759,6 +3756,15 @@ function wrapLazyTurnBoxWithRouting(services, ids, args) {
3759
3756
  },
3760
3757
  ...services.onSandboxOperation ? { onOperation: services.onSandboxOperation } : {},
3761
3758
  ...args.onFirstOperation ? { onFirstOperation: args.onFirstOperation } : {},
3759
+ providerCommandHandle: admittedCommandHandle,
3760
+ ...ids.workspaceMutationFence ? {
3761
+ providerCommandPersistence: (process) => retainedProviderCommandPersistence(db, {
3762
+ accountId: ids.workspaceMutationFence.accountId,
3763
+ workspaceId: ids.workspaceId,
3764
+ sessionId: ids.sessionId,
3765
+ processId: process.id
3766
+ })
3767
+ } : {},
3762
3768
  ...beforeMutation ? { beforeMutation } : {},
3763
3769
  ...afterMutation ? { afterMutation } : {},
3764
3770
  ...beforeProcessMutation ? { beforeProcessMutation } : {},
@@ -4204,9 +4210,21 @@ async function reconcileAutomaticSessionTitleFanout(svc, limit = 100, overrides
4204
4210
  async function reconcilePendingSessionWorkflowWakes(svc, limit = 1e3, overrides = {}) {
4205
4211
  const claimPendingSessionWorkflowWakesFn = overrides.claimPendingSessionWorkflowWakes ?? claimPendingSessionWorkflowWakes;
4206
4212
  if (!svc.wakeSessionWorkflow) {
4207
- return { claimed: 0, delivered: 0, failed: 0 };
4213
+ return {
4214
+ claimed: 0,
4215
+ signaled: 0,
4216
+ delivered: 0,
4217
+ pendingAdmission: 0,
4218
+ unconfirmed: 0,
4219
+ failed: 0,
4220
+ pendingAdmissionBlockers: {}
4221
+ };
4208
4222
  }
4209
4223
  const repairs = await claimPendingSessionWorkflowWakesFn(svc.db, limit);
4224
+ let signaled = 0;
4225
+ let pendingAdmission = 0;
4226
+ let unconfirmed = 0;
4227
+ const pendingAdmissionBlockers = {};
4210
4228
  let delivered = 0;
4211
4229
  let failed = 0;
4212
4230
  const queue = [...repairs];
@@ -4214,16 +4232,31 @@ async function reconcilePendingSessionWorkflowWakes(svc, limit = 1e3, overrides
4214
4232
  for (; ; ) {
4215
4233
  const repair = queue.shift();
4216
4234
  if (!repair) return;
4235
+ let signalAccepted = false;
4236
+ const onSignalAccepted = () => {
4237
+ if (signalAccepted) return;
4238
+ signalAccepted = true;
4239
+ signaled += 1;
4240
+ };
4217
4241
  try {
4218
- await svc.wakeSessionWorkflow({
4242
+ const receipt = await svc.wakeSessionWorkflow({
4219
4243
  accountId: repair.accountId,
4220
4244
  workspaceId: repair.workspaceId,
4221
4245
  sessionId: repair.sessionId,
4222
4246
  workflowId: repair.temporalWorkflowId,
4223
4247
  wakeRevision: repair.wakeRevision,
4224
- ...repair.interruptionRequested ? { interruptionRequested: true } : {}
4248
+ ...repair.interruptionRequested ? { interruptionRequested: true } : {},
4249
+ onSignalAccepted
4225
4250
  });
4226
- delivered += 1;
4251
+ onSignalAccepted();
4252
+ if (receipt?.action === "acknowledged") {
4253
+ delivered += 1;
4254
+ } else if (receipt?.action === "pending_admission") {
4255
+ pendingAdmission += 1;
4256
+ pendingAdmissionBlockers[receipt.blocker] = (pendingAdmissionBlockers[receipt.blocker] ?? 0) + 1;
4257
+ } else {
4258
+ unconfirmed += 1;
4259
+ }
4227
4260
  } catch (error) {
4228
4261
  failed += 1;
4229
4262
  await markSessionWorkflowWakeFailed(
@@ -4235,7 +4268,15 @@ async function reconcilePendingSessionWorkflowWakes(svc, limit = 1e3, overrides
4235
4268
  }
4236
4269
  });
4237
4270
  await Promise.all(workers);
4238
- return { claimed: repairs.length, delivered, failed };
4271
+ return {
4272
+ claimed: repairs.length,
4273
+ signaled,
4274
+ delivered,
4275
+ pendingAdmission,
4276
+ unconfirmed,
4277
+ failed,
4278
+ pendingAdmissionBlockers
4279
+ };
4239
4280
  }
4240
4281
  function childCompletionPayload(child, goal) {
4241
4282
  return {
@@ -4964,6 +5005,10 @@ function classifySandboxLogicalProvisionFailure(backend, error) {
4964
5005
  }
4965
5006
  function isLazySandboxProvisionRetryable(error) {
4966
5007
  const chain = sandboxProvisionErrorChain(error);
5008
+ if (chain.some(
5009
+ (value) => value instanceof SandboxLeaseTransitionError2 && value.reason === "rotation_in_progress"
5010
+ ))
5011
+ return false;
4967
5012
  if (chain.some(
4968
5013
  (value) => value instanceof SandboxImageConflictError || value instanceof SandboxRigConflictError || value instanceof SandboxLeaseRecoveryBlockedError2
4969
5014
  )) {
@@ -5351,6 +5396,512 @@ import {
5351
5396
  mcpTransportRequestFailureDiagnostic
5352
5397
  } from "@opengeni/runtime/mcp-network";
5353
5398
  import { ApplicationFailure, CancelledFailure as CancelledFailure2 } from "@temporalio/activity";
5399
+
5400
+ // src/activities/run-input.ts
5401
+ import {
5402
+ MODEL_ATTACHMENT_REFS_FIELD,
5403
+ MODEL_ATTACHMENT_CATALOG_MARKER,
5404
+ FileResourceRef,
5405
+ resourceMountPath
5406
+ } from "@opengeni/contracts";
5407
+ import { createHash as createHash2 } from "crypto";
5408
+ import {
5409
+ getActiveSessionHistoryItemsPaged,
5410
+ getFilesForSubject,
5411
+ getSandboxSessionEnvelope as getSandboxSessionEnvelope2,
5412
+ listSessionSystemUpdatesForTurn,
5413
+ listTurnOpenSuffixToolCalls
5414
+ } from "@opengeni/db";
5415
+ import {
5416
+ projectHistoryForProvider,
5417
+ projectRejectedProviderArtifactsFromSerializedRunState,
5418
+ projectRejectedReasoningArtifact,
5419
+ hasOpaqueProviderArtifact
5420
+ } from "@opengeni/runtime";
5421
+ function projectRejectedProviderArtifacts(rows) {
5422
+ const out = [];
5423
+ for (const row of rows) {
5424
+ if (!row.providerArtifactInvalidatedAt) {
5425
+ out.push(row.item);
5426
+ continue;
5427
+ }
5428
+ const type = typeof row.item.type === "string" ? row.item.type : void 0;
5429
+ if (type === "reasoning") {
5430
+ out.push(projectRejectedReasoningArtifact(row.item));
5431
+ continue;
5432
+ }
5433
+ if (type === "compaction") {
5434
+ continue;
5435
+ }
5436
+ out.push(row.item);
5437
+ }
5438
+ return out;
5439
+ }
5440
+ async function measureHistoryPreparationPhase(options, phase, operation) {
5441
+ const startedAt = performance.now();
5442
+ let outcome = "completed";
5443
+ try {
5444
+ return await operation();
5445
+ } catch (error) {
5446
+ outcome = "failed";
5447
+ throw error;
5448
+ } finally {
5449
+ try {
5450
+ options.onPreparationPhase?.({
5451
+ phase,
5452
+ outcome,
5453
+ durationSeconds: (performance.now() - startedAt) / 1e3
5454
+ });
5455
+ } catch {
5456
+ }
5457
+ }
5458
+ }
5459
+ var MAX_INLINE_MODEL_ATTACHMENT_BYTES = 20 * 1024 * 1024;
5460
+ var MAX_RETAINED_MODEL_ATTACHMENT_BYTES = 64 * 1024 * 1024;
5461
+ var RetainedAttachmentTransportLimitError = class extends Error {
5462
+ constructor() {
5463
+ super(
5464
+ "Active uploaded images exceed the 64 MiB inline transport limit. History was preserved and no new image bytes were downloaded. Start a smaller conversation or fork before the image-heavy messages."
5465
+ );
5466
+ this.name = "RetainedAttachmentTransportLimitError";
5467
+ }
5468
+ };
5469
+ var MODEL_IMAGE_CONTENT_TYPES = /* @__PURE__ */ new Set(["image/gif", "image/jpeg", "image/png", "image/webp"]);
5470
+ var MODEL_FILE_CONTENT_TYPES = /* @__PURE__ */ new Set([
5471
+ "application/json",
5472
+ "application/pdf",
5473
+ "application/x-yaml",
5474
+ "application/yaml"
5475
+ ]);
5476
+ var BLOCKED_TEXT_CONTENT_TYPES = /* @__PURE__ */ new Set([
5477
+ "text/css",
5478
+ "text/html",
5479
+ "text/javascript",
5480
+ "text/xml"
5481
+ ]);
5482
+ function safeErrorType(error) {
5483
+ if (!(error instanceof Error)) return typeof error;
5484
+ const name = error.name.trim();
5485
+ return /^[A-Za-z][A-Za-z0-9_.-]{0,63}$/.test(name) ? name : "Error";
5486
+ }
5487
+ function modelAttachmentDescriptor(contentType) {
5488
+ const normalized = contentType.toLowerCase().split(";", 1)[0]?.trim() ?? "";
5489
+ if (MODEL_IMAGE_CONTENT_TYPES.has(normalized)) {
5490
+ return { kind: "image", contentType: normalized };
5491
+ }
5492
+ if (MODEL_FILE_CONTENT_TYPES.has(normalized) || normalized.startsWith("text/") && !BLOCKED_TEXT_CONTENT_TYPES.has(normalized)) {
5493
+ return { kind: "file", contentType: normalized };
5494
+ }
5495
+ return null;
5496
+ }
5497
+ async function modelAttachmentContentForFiles(files, readFileBytes, options = {}) {
5498
+ const selected = [];
5499
+ let remainingBytes = options.retainAll ? Number.POSITIVE_INFINITY : MAX_INLINE_MODEL_ATTACHMENT_BYTES;
5500
+ for (const file of files) {
5501
+ const descriptor = modelAttachmentDescriptor(file.contentType);
5502
+ const checksum = file.sha256?.trim().toLowerCase() ?? "";
5503
+ if (file.status !== "ready" || !descriptor || descriptor.kind !== "image" || file.sizeBytes > MAX_INLINE_MODEL_ATTACHMENT_BYTES || file.sizeBytes > remainingBytes || !/^[a-f0-9]{64}$/.test(checksum)) {
5504
+ continue;
5505
+ }
5506
+ selected.push({ file, descriptor, checksum });
5507
+ remainingBytes -= file.sizeBytes;
5508
+ }
5509
+ const attachments = new Array(selected.length);
5510
+ let cursor = 0;
5511
+ const worker = async () => {
5512
+ while (cursor < selected.length) {
5513
+ const index = cursor++;
5514
+ const { file, descriptor, checksum } = selected[index];
5515
+ try {
5516
+ const bytes = await readFileBytes(file);
5517
+ if (bytes.byteLength !== file.sizeBytes) {
5518
+ console.error("model attachment bytes did not match finalized metadata", {
5519
+ fileId: file.id,
5520
+ expectedSizeBytes: file.sizeBytes,
5521
+ actualSizeBytes: bytes.byteLength
5522
+ });
5523
+ continue;
5524
+ }
5525
+ if (createHash2("sha256").update(bytes).digest("hex") !== checksum) {
5526
+ console.error("model attachment checksum did not match finalized metadata", {
5527
+ fileId: file.id
5528
+ });
5529
+ continue;
5530
+ }
5531
+ attachments[index] = {
5532
+ kind: descriptor.kind,
5533
+ fileId: file.id,
5534
+ filename: file.safeFilename,
5535
+ contentType: descriptor.contentType,
5536
+ dataUrl: `data:${descriptor.contentType};base64,${Buffer.from(bytes).toString("base64")}`
5537
+ };
5538
+ } catch (error) {
5539
+ console.error("model attachment content read failed; retaining sandbox path fallback", {
5540
+ fileId: file.id,
5541
+ errorType: safeErrorType(error)
5542
+ });
5543
+ }
5544
+ }
5545
+ };
5546
+ await Promise.all(
5547
+ Array.from({ length: Math.min(8, selected.length) }, async () => await worker())
5548
+ );
5549
+ return attachments.filter(
5550
+ (attachment) => attachment !== void 0
5551
+ );
5552
+ }
5553
+ function attachmentRefsFromItem(item) {
5554
+ const raw = item[MODEL_ATTACHMENT_REFS_FIELD];
5555
+ if (!Array.isArray(raw)) return [];
5556
+ const refs = [];
5557
+ for (const candidate of raw) {
5558
+ const parsed = FileResourceRef.safeParse(candidate);
5559
+ if (parsed.success) refs.push(parsed.data);
5560
+ }
5561
+ return refs;
5562
+ }
5563
+ function attachmentReceiptText(ref, file) {
5564
+ if (!file) {
5565
+ return `[Earlier attachment: fileId=${ref.fileId}; mountDirectory=${resourceMountPath(ref)}. Use the existing file there, or call files__files_get_download_url with this fileId and download it with the shell.]`;
5566
+ }
5567
+ const path = sandboxFilePath(ref, file);
5568
+ return `[Attachment: ${file.safeFilename}; fileId=${file.id}; type=${file.contentType}; bytes=${file.sizeBytes}; path=${path}. If the local path is absent, call files__files_get_download_url with this fileId and download it with the shell.]`;
5569
+ }
5570
+ function createModelHistoryAttachmentProjector(policy, readFileBytes, loadAuthorizedFiles) {
5571
+ const contentById = /* @__PURE__ */ new Map();
5572
+ const attemptedContentIds = /* @__PURE__ */ new Set();
5573
+ const fileById = /* @__PURE__ */ new Map();
5574
+ const resolvedFileIds = /* @__PURE__ */ new Set();
5575
+ const retainedByteSizes = /* @__PURE__ */ new Map();
5576
+ return async (items, options = {}) => {
5577
+ for (const file of options.inlineFiles ?? []) {
5578
+ fileById.set(file.id, file);
5579
+ resolvedFileIds.add(file.id);
5580
+ }
5581
+ const refsByIndex = /* @__PURE__ */ new Map();
5582
+ const orderedFileIds = [];
5583
+ const seenFileIds = /* @__PURE__ */ new Set();
5584
+ for (let index = 0; index < items.length; index += 1) {
5585
+ const refs = attachmentRefsFromItem(items[index]);
5586
+ if (refs.length === 0) continue;
5587
+ refsByIndex.set(index, refs);
5588
+ for (const ref of refs) {
5589
+ if (items[index][MODEL_ATTACHMENT_CATALOG_MARKER] === true || seenFileIds.has(ref.fileId))
5590
+ continue;
5591
+ seenFileIds.add(ref.fileId);
5592
+ orderedFileIds.push(ref.fileId);
5593
+ }
5594
+ }
5595
+ if (refsByIndex.size === 0) return items;
5596
+ const unresolved = orderedFileIds.filter((id) => !resolvedFileIds.has(id));
5597
+ if (loadAuthorizedFiles && unresolved.length > 0) {
5598
+ const files = await loadAuthorizedFiles(unresolved);
5599
+ for (const file of files) fileById.set(file.id, file);
5600
+ for (const id of unresolved) resolvedFileIds.add(id);
5601
+ }
5602
+ if (readFileBytes) {
5603
+ const admitted = new Map(retainedByteSizes);
5604
+ let requestImageBytes = 0;
5605
+ for (const [index, refs] of refsByIndex) {
5606
+ if (items[index][MODEL_ATTACHMENT_CATALOG_MARKER] === true) continue;
5607
+ for (const ref of refs) {
5608
+ const file = fileById.get(ref.fileId);
5609
+ if (!file || !policy.supportsImageInput || file.status !== "ready" || file.sizeBytes > MAX_INLINE_MODEL_ATTACHMENT_BYTES || modelAttachmentDescriptor(file.contentType)?.kind !== "image" || !/^[a-f0-9]{64}$/i.test(file.sha256?.trim() ?? ""))
5610
+ continue;
5611
+ requestImageBytes += file.sizeBytes;
5612
+ admitted.set(file.id, file.sizeBytes);
5613
+ }
5614
+ }
5615
+ const turnImageBytes = [...admitted.values()].reduce((sum, bytes) => sum + bytes, 0);
5616
+ if (requestImageBytes > MAX_RETAINED_MODEL_ATTACHMENT_BYTES || turnImageBytes > MAX_RETAINED_MODEL_ATTACHMENT_BYTES) {
5617
+ throw new RetainedAttachmentTransportLimitError();
5618
+ }
5619
+ for (const [id, bytes] of admitted) retainedByteSizes.set(id, bytes);
5620
+ const readable = [...orderedFileIds].reverse().map((id) => fileById.get(id)).filter((file) => {
5621
+ if (!file || attemptedContentIds.has(file.id)) return false;
5622
+ const descriptor = modelAttachmentDescriptor(file.contentType);
5623
+ return Boolean(descriptor && descriptor.kind === "image" && policy.supportsImageInput);
5624
+ });
5625
+ for (const file of readable) attemptedContentIds.add(file.id);
5626
+ const content = await modelAttachmentContentForFiles(readable, readFileBytes, {
5627
+ retainAll: true
5628
+ });
5629
+ const loadedIds = new Set(content.map((entry) => entry.fileId));
5630
+ for (const file of readable) {
5631
+ if (file.status === "ready" && file.sizeBytes <= MAX_INLINE_MODEL_ATTACHMENT_BYTES && /^[a-f0-9]{64}$/i.test(file.sha256 ?? "") && !loadedIds.has(file.id)) {
5632
+ for (const candidate of readable) attemptedContentIds.delete(candidate.id);
5633
+ throw new Error(`Retained attachment bytes unavailable or invalid: ${file.id}`);
5634
+ }
5635
+ }
5636
+ for (const attachment of content) contentById.set(attachment.fileId, attachment);
5637
+ }
5638
+ const projected = [...items];
5639
+ for (const [index, refs] of refsByIndex) {
5640
+ const original = items[index];
5641
+ const existingContent = Array.isArray(original.content) ? [...original.content] : [{ type: "input_text", text: String(original.content ?? "") }];
5642
+ const attachmentParts = refs.flatMap((ref) => {
5643
+ const currentFile = original[MODEL_ATTACHMENT_CATALOG_MARKER] === true ? void 0 : fileById.get(ref.fileId);
5644
+ const attachment = currentFile ? contentById.get(ref.fileId) : void 0;
5645
+ const receipt = {
5646
+ type: "input_text",
5647
+ text: attachmentReceiptText(ref, currentFile)
5648
+ };
5649
+ if (!attachment || attachment.kind !== "image") {
5650
+ return [receipt];
5651
+ }
5652
+ return [receipt, { type: "input_image", image: attachment.dataUrl }];
5653
+ });
5654
+ const clone = {
5655
+ ...original,
5656
+ content: [...existingContent, ...attachmentParts]
5657
+ };
5658
+ delete clone[MODEL_ATTACHMENT_REFS_FIELD];
5659
+ projected[index] = clone;
5660
+ }
5661
+ return projected;
5662
+ };
5663
+ }
5664
+ function withCurrentUserAttachmentRefs(historyItems, refs) {
5665
+ if (refs.length === 0) return historyItems;
5666
+ for (let index = historyItems.length - 1; index >= 0; index -= 1) {
5667
+ const item = historyItems[index];
5668
+ if (item.type !== "message" || item.role !== "user") continue;
5669
+ const existing = attachmentRefsFromItem(item);
5670
+ const existingIds = new Set(existing.map((ref) => ref.fileId));
5671
+ const additions = refs.filter((ref) => !existingIds.has(ref.fileId));
5672
+ if (additions.length === 0) return historyItems;
5673
+ const projected = [...historyItems];
5674
+ projected[index] = { ...item, [MODEL_ATTACHMENT_REFS_FIELD]: [...existing, ...additions] };
5675
+ return projected;
5676
+ }
5677
+ return historyItems;
5678
+ }
5679
+ async function turnInput(db, runtime, agent, trigger, options) {
5680
+ if (!trigger) {
5681
+ throw new Error("Missing trigger event");
5682
+ }
5683
+ const updates = await measureHistoryPreparationPhase(
5684
+ options,
5685
+ "system_update_load",
5686
+ async () => await listSessionSystemUpdatesForTurn(
5687
+ db,
5688
+ trigger.workspaceId,
5689
+ trigger.sessionId,
5690
+ options.turnId
5691
+ )
5692
+ );
5693
+ if (updates.some((update) => !update.deliveredHistoryItemId)) {
5694
+ throw new Error("Delivered internal update has no durable model-memory batch");
5695
+ }
5696
+ const internalContext = joinInternalContext(
5697
+ options.recovering ? [
5698
+ "[OpenGeni inference recovery]",
5699
+ "Continue the same inference from durable conversation and sandbox state. A previous execution stopped before it could finish. Do not repeat completed side effects; inspect actual state when uncertain."
5700
+ ].join("\n") : void 0,
5701
+ options.unavailableSandboxFilesNote,
5702
+ options.runCredentialsNote,
5703
+ options.mcpAvailabilityNote
5704
+ );
5705
+ if (trigger.type === "user.message") {
5706
+ const payload = trigger.payload;
5707
+ const hasAnnotations = Array.isArray(payload.annotations) && payload.annotations.length > 0;
5708
+ if (typeof payload.text !== "string" || payload.text.trim().length === 0 && !hasAnnotations) {
5709
+ throw new Error("user.message payload is missing text and annotations");
5710
+ }
5711
+ const resources = Array.isArray(payload.resources) ? payload.resources : [];
5712
+ const fileAttachments = await measureHistoryPreparationPhase(
5713
+ options,
5714
+ "current_attachment_resolution",
5715
+ async () => await resolveUserMessageFileAttachments(
5716
+ db,
5717
+ options.fileAuthority.accountId,
5718
+ trigger.workspaceId,
5719
+ options.fileAuthority.subjectId,
5720
+ resources
5721
+ )
5722
+ );
5723
+ const attachmentContext = userMessageAttachmentsContext(fileAttachments);
5724
+ return await messageInput(
5725
+ db,
5726
+ runtime,
5727
+ agent,
5728
+ trigger,
5729
+ void 0,
5730
+ joinInternalContext(internalContext, attachmentContext),
5731
+ fileAttachments,
5732
+ options.providerApi,
5733
+ options.projectCanonicalHistory,
5734
+ options.materializeModelHistory,
5735
+ options.projectModelHistory,
5736
+ options.loadActiveHistory,
5737
+ options
5738
+ );
5739
+ }
5740
+ if (trigger.type === "system.update.delivered") {
5741
+ if (updates.length === 0) {
5742
+ throw new Error("Internal update inference has no delivered updates");
5743
+ }
5744
+ return await messageInput(
5745
+ db,
5746
+ runtime,
5747
+ agent,
5748
+ trigger,
5749
+ void 0,
5750
+ internalContext,
5751
+ [],
5752
+ options.providerApi,
5753
+ options.projectCanonicalHistory,
5754
+ options.materializeModelHistory,
5755
+ options.projectModelHistory,
5756
+ options.loadActiveHistory,
5757
+ options
5758
+ );
5759
+ }
5760
+ if (trigger.type === "user.approvalDecision" || trigger.type === "user.humanInputResponse") {
5761
+ return await openSuffixMessageInput(db, runtime, agent, trigger, internalContext, options);
5762
+ }
5763
+ throw new Error(`Unsupported trigger event type: ${trigger.type}`);
5764
+ }
5765
+ function joinInternalContext(...parts) {
5766
+ const content = parts.map((part) => part?.trim()).filter((part) => Boolean(part));
5767
+ return content.length > 0 ? content.join("\n\n") : void 0;
5768
+ }
5769
+ async function openSuffixMessageInput(db, runtime, agent, trigger, internalContext, options) {
5770
+ const suffixRows = await listTurnOpenSuffixToolCalls(
5771
+ db,
5772
+ trigger.workspaceId,
5773
+ trigger.sessionId,
5774
+ options.turnId
5775
+ );
5776
+ if (suffixRows.length === 0) {
5777
+ throw new Error("Open suffix resume has no interruption rows");
5778
+ }
5779
+ if (suffixRows.some((row) => row.resultItem == null)) {
5780
+ throw new Error("Open suffix resume still has unresolved members");
5781
+ }
5782
+ return await messageInput(
5783
+ db,
5784
+ runtime,
5785
+ agent,
5786
+ trigger,
5787
+ void 0,
5788
+ internalContext,
5789
+ [],
5790
+ options.providerApi,
5791
+ options.projectCanonicalHistory,
5792
+ options.materializeModelHistory,
5793
+ options.projectModelHistory,
5794
+ options.loadActiveHistory,
5795
+ options
5796
+ );
5797
+ }
5798
+ async function messageInput(db, runtime, agent, trigger, text, internalContext, currentAttachments = [], providerApi = "responses", projectCanonicalHistory, materializeModelHistory, projectModelHistory, loadActiveHistory = getActiveSessionHistoryItemsPaged, preparationOptions = {}) {
5799
+ const currentAttachmentRefs = currentAttachments.map((attachment) => attachment.resource);
5800
+ const [stored, envelope] = await Promise.all([
5801
+ measureHistoryPreparationPhase(
5802
+ preparationOptions,
5803
+ "durable_history_load",
5804
+ async () => loadActiveHistory(db, trigger.workspaceId, trigger.sessionId)
5805
+ ),
5806
+ measureHistoryPreparationPhase(
5807
+ preparationOptions,
5808
+ "sandbox_envelope_load",
5809
+ async () => getSandboxSessionEnvelope2(db, trigger.workspaceId, trigger.sessionId)
5810
+ )
5811
+ ]);
5812
+ const canonicalView = await measureHistoryPreparationPhase(
5813
+ preparationOptions,
5814
+ "canonical_projection",
5815
+ async () => {
5816
+ const active = projectRejectedProviderArtifacts(stored);
5817
+ return projectCanonicalHistory ? await projectCanonicalHistory(active) : active;
5818
+ }
5819
+ );
5820
+ const providerView = await measureHistoryPreparationPhase(
5821
+ preparationOptions,
5822
+ "provider_projection",
5823
+ () => projectHistoryForProvider(canonicalView, providerApi)
5824
+ );
5825
+ const referencedHistory = await measureHistoryPreparationPhase(
5826
+ preparationOptions,
5827
+ "attachment_ref_projection",
5828
+ () => withCurrentUserAttachmentRefs(providerView, currentAttachmentRefs)
5829
+ );
5830
+ const materializedHistory = await measureHistoryPreparationPhase(
5831
+ preparationOptions,
5832
+ "screenshot_materialization",
5833
+ async () => materializeModelHistory ? await materializeModelHistory(referencedHistory) : referencedHistory
5834
+ );
5835
+ const historyItems = await measureHistoryPreparationPhase(
5836
+ preparationOptions,
5837
+ "model_attachment_projection",
5838
+ async () => projectModelHistory ? await projectModelHistory(materializedHistory, {
5839
+ inlineFiles: currentAttachments.map((attachment) => attachment.file)
5840
+ }) : materializedHistory
5841
+ );
5842
+ const prepared = await measureHistoryPreparationPhase(
5843
+ preparationOptions,
5844
+ "runtime_input_assembly",
5845
+ async () => await runtime.prepareInput(agent, {
5846
+ kind: "message",
5847
+ ...text ? { text } : {},
5848
+ ...internalContext ? { internalContext } : {},
5849
+ historyItems,
5850
+ sandboxEnvelope: envelope,
5851
+ ...projectModelHistory ? { modelInputAlreadyProjected: true } : {}
5852
+ })
5853
+ );
5854
+ const providerArtifactCandidates = await measureHistoryPreparationPhase(
5855
+ preparationOptions,
5856
+ "artifact_candidate_scan",
5857
+ () => {
5858
+ const preparedItems = Array.isArray(prepared.input) ? new Set(prepared.input) : /* @__PURE__ */ new Set();
5859
+ return {
5860
+ knownHistoryItemIds: stored.map((row) => row.id),
5861
+ historyItemIds: stored.filter(
5862
+ (row) => row.providerArtifactInvalidatedAt === null && hasOpaqueProviderArtifact(row.item) && preparedItems.has(row.item)
5863
+ ).map((row) => row.id)
5864
+ };
5865
+ }
5866
+ );
5867
+ return {
5868
+ input: prepared,
5869
+ persistedHistoryCount: prepared.persistedHistoryCount,
5870
+ providerArtifactCandidates
5871
+ };
5872
+ }
5873
+ async function resolveUserMessageFileAttachments(db, accountId, workspaceId, subjectId, resources) {
5874
+ const fileResources = resources.filter(
5875
+ (resource) => resource.kind === "file"
5876
+ );
5877
+ if (fileResources.length === 0) return [];
5878
+ const files = await getFilesForSubject(db, {
5879
+ accountId,
5880
+ workspaceId,
5881
+ subjectId,
5882
+ fileIds: fileResources.map((resource) => resource.fileId)
5883
+ });
5884
+ const fileById = new Map(files.map((file) => [file.id, file]));
5885
+ return fileResources.map((resource) => {
5886
+ const file = fileById.get(resource.fileId);
5887
+ if (!file) throw new Error(`File not found: ${resource.fileId}`);
5888
+ return { resource, file };
5889
+ });
5890
+ }
5891
+ function userMessageAttachmentsContext(attachments) {
5892
+ const attachedFiles = attachments.map(
5893
+ ({ resource, file }) => `- ${file.filename} (${file.contentType}, ${file.sizeBytes} bytes): ${sandboxFilePath(resource, file)}`
5894
+ );
5895
+ if (attachedFiles.length === 0) {
5896
+ return void 0;
5897
+ }
5898
+ return ["Attached files are available in the sandbox:", ...attachedFiles].join("\n");
5899
+ }
5900
+ function sandboxFilePath(resource, file) {
5901
+ return `${resourceMountPath(resource)}/${file.safeFilename}`;
5902
+ }
5903
+
5904
+ // src/activities/agent-turn/errors.ts
5354
5905
  import {
5355
5906
  CodexReloginRequired,
5356
5907
  classifyCodexResponseTimeoutError,
@@ -5782,6 +6333,9 @@ function findPostgresDriverError(error) {
5782
6333
  return null;
5783
6334
  }
5784
6335
  function agentRunFailurePayload(error, options = {}) {
6336
+ if (error instanceof RetainedAttachmentTransportLimitError) {
6337
+ return { error: error.message, code: "retained_attachment_transport_limit", retryable: false };
6338
+ }
5785
6339
  if (error instanceof MandatoryHistoryPersistenceError) {
5786
6340
  const underlying = isSessionEventPersistenceError(error.cause) ? agentRunFailurePayload(error.cause, options) : {
5787
6341
  error: error.cause instanceof Error ? error.cause.message : String(error.cause)
@@ -6079,7 +6633,6 @@ export {
6079
6633
  rigProviderImageSourceImage,
6080
6634
  settingsWithPackSandboxImage,
6081
6635
  resolveWorkspacePackRuntime,
6082
- resolveWorkspaceInstalledSkillRuntime,
6083
6636
  createRuntimeBatcher,
6084
6637
  currentActivityContext,
6085
6638
  startActivityHeartbeat,
@@ -6114,6 +6667,9 @@ export {
6114
6667
  incidentTelemetryAuthorityFence,
6115
6668
  resolveIncidentTelemetryResponderMetadata,
6116
6669
  validateIncidentTelemetrySystemUpdateAuthority,
6670
+ projectRejectedProviderArtifacts,
6671
+ createModelHistoryAttachmentProjector,
6672
+ turnInput,
6117
6673
  SandboxDeadlineRotationError,
6118
6674
  turnOperationCancellationFailure,
6119
6675
  throwIfTurnOperationCancelled,
@@ -6166,4 +6722,4 @@ export {
6166
6722
  codexUsageLimitFailurePayload,
6167
6723
  CODEX_USAGE_LIMIT_MAX_RESUME_MS
6168
6724
  };
6169
- //# sourceMappingURL=chunk-7LS42PHP.js.map
6725
+ //# sourceMappingURL=chunk-C54VDT6I.js.map