@opengeni/worker-bundle 0.27.0-canary.0 → 0.27.2-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
@@ -33,7 +33,7 @@ import {
33
33
  scheduledUserMessagePayload,
34
34
  withFirstPartyTools,
35
35
  workflowIdForSession
36
- } from "./chunk-7LS42PHP.js";
36
+ } from "./chunk-C54VDT6I.js";
37
37
  import {
38
38
  inspectOpenSandboxKubernetesInventory,
39
39
  recordCreditBalanceGauges,
@@ -53,7 +53,7 @@ import {
53
53
  recordTurnsQueuedGauge,
54
54
  recordWorkerDeathRecoveryMetrics,
55
55
  runtimeMetricsHooksForObservability
56
- } from "./chunk-D4ZEFOYH.js";
56
+ } from "./chunk-BARTLVBK.js";
57
57
 
58
58
  // src/activities/browser-state-artifact-reaper.ts
59
59
  import {
@@ -159,6 +159,7 @@ import {
159
159
  claimAutomationRun,
160
160
  settleAutomationRun
161
161
  } from "@opengeni/db";
162
+ import { SessionSkills } from "@opengeni/contracts";
162
163
 
163
164
  // src/activities/agent-run-admission.ts
164
165
  import { configuredStaticUsageLimits } from "@opengeni/config";
@@ -355,7 +356,8 @@ function createAutomationActivities(services, options = {}) {
355
356
  workspaceId: input.workspaceId,
356
357
  initialMessage: accepted.initialMessage,
357
358
  resources: template.resources,
358
- skills: template.skills,
359
+ skills: SessionSkills.parse(template.skills),
360
+ bundledSkillIds: template.bundledSkillIds,
359
361
  tools: template.tools,
360
362
  toolPolicy: { mode: "explicit", inheritedFromSessionId: null },
361
363
  model,
@@ -5188,6 +5190,7 @@ function createRigVerificationActivities(services) {
5188
5190
 
5189
5191
  // src/activities/sandbox-lease.ts
5190
5192
  import { createHash as createHash3, randomUUID as randomUUID2 } from "crypto";
5193
+ import { retainedProviderCommandPersistence } from "@opengeni/db/retained-provider-commands";
5191
5194
  import { Context } from "@temporalio/activity";
5192
5195
  import { OpLostReason, OpState } from "@opengeni/agent-proto";
5193
5196
  import {
@@ -5250,6 +5253,7 @@ import {
5250
5253
  inspectModalSandboxLifecycle,
5251
5254
  isExecSessionLostBanner,
5252
5255
  isProviderSandboxNotFoundError,
5256
+ isProviderSandboxGoneDuringRoutedOperation,
5253
5257
  NatsControlRpc,
5254
5258
  NatsOpStreamTransport,
5255
5259
  OpStreamExecClient,
@@ -5378,8 +5382,14 @@ function createSandboxLeaseActivities(services, options = {}) {
5378
5382
  try {
5379
5383
  const { db, settings, observability } = await services();
5380
5384
  const timing = sandboxDrainTiming(settings);
5385
+ const onUnobservableCommandDrainError = (error) => {
5386
+ observability.warn("sandbox reaper: unobservable command drain inspection failed", {
5387
+ error: error instanceof Error ? error.message : String(error)
5388
+ });
5389
+ };
5381
5390
  if (!settings.sandboxOwnershipEnabled) {
5382
5391
  const drainableInventory2 = await reapStaleLeaseHoldersGlobal(db, {
5392
+ onUnobservableCommandDrainError,
5383
5393
  viewerHolderTtlMs: settings.sandboxViewerHolderTtlMs,
5384
5394
  turnHolderTtlMs: settings.sandboxLeaseTtlMs,
5385
5395
  interactionHolderTtlMs: settings.sandboxInteractionHolderTtlMs,
@@ -5406,6 +5416,7 @@ function createSandboxLeaseActivities(services, options = {}) {
5406
5416
  });
5407
5417
  recordSandboxDeadlineRotationsRequested(observability, rotationsRequested);
5408
5418
  const drainableInventory = await reapStaleLeaseHoldersGlobal(db, {
5419
+ onUnobservableCommandDrainError,
5409
5420
  viewerHolderTtlMs: settings.sandboxViewerHolderTtlMs,
5410
5421
  // Dead-worker turn holders: a live holder is touched every 10s from the
5411
5422
  // moment it is registered (resumeBoxForTurn's holder-liveness loop covers
@@ -6160,8 +6171,8 @@ async function reconcileTerminalRetainedProcesses(db, settings, observability, p
6160
6171
  lease,
6161
6172
  process,
6162
6173
  claim.ownerState === "background_stopping" ? "cancel" : "observe",
6163
- async (result, chunkId) => {
6164
- if (typeof result !== "string" || isExecSessionLostBanner(result, process.providerSessionId))
6174
+ async (result, chunkId, stream, streamFidelity) => {
6175
+ if (typeof result !== "string" || !stream && isExecSessionLostBanner(result, process.providerSessionId))
6165
6176
  return;
6166
6177
  const events = await appendSessionCommandOutput(db, {
6167
6178
  accountId: process.accountId,
@@ -6169,13 +6180,19 @@ async function reconcileTerminalRetainedProcesses(db, settings, observability, p
6169
6180
  sessionId: process.sessionId,
6170
6181
  commandId: process.id,
6171
6182
  chunkId,
6172
- stream: "stdout",
6173
- streamFidelity: "merged",
6174
- chunk: stripExecBanner(result)
6183
+ stream: stream ?? "stdout",
6184
+ streamFidelity: streamFidelity ?? (stream ? "separate" : "merged"),
6185
+ chunk: stream ? result : stripExecBanner(result)
6175
6186
  });
6176
6187
  if (events.length && bus)
6177
6188
  await bus.publish(process.workspaceId, process.sessionId, events).catch(() => void 0);
6178
- }
6189
+ },
6190
+ retainedProviderCommandPersistence(db, {
6191
+ accountId: process.accountId,
6192
+ workspaceId: process.workspaceId,
6193
+ sessionId: process.sessionId,
6194
+ processId: process.id
6195
+ })
6179
6196
  );
6180
6197
  } catch (error) {
6181
6198
  observability.warn("sandbox reaper: retained-process provider probe failed", {
@@ -6314,11 +6331,11 @@ async function deferRetainedProcessClaim(db, settings, observability, process, e
6314
6331
  }
6315
6332
  }
6316
6333
  function retainedProcessReconciliationDeferral(settings, process, outcome) {
6317
- const bindingQuarantine = process.reconcileAttempts >= RETAINED_PROCESS_BINDING_QUARANTINE_AFTER_ATTEMPTS && (outcome === "provider_binding_missing" || outcome === "provider_binding_mismatch");
6334
+ const bindingQuarantine = process.reconcileAttempts >= RETAINED_PROCESS_BINDING_QUARANTINE_AFTER_ATTEMPTS && (outcome === "provider_binding_missing" || outcome === "provider_binding_mismatch" || outcome === "process_observation_unavailable");
6318
6335
  if (bindingQuarantine) {
6319
6336
  return {
6320
6337
  durableOutcome: `quarantined_${outcome}`,
6321
- metricOutcome: outcome === "provider_binding_missing" ? "quarantined_binding_missing" : "quarantined_binding_mismatch",
6338
+ metricOutcome: outcome === "provider_binding_missing" ? "quarantined_binding_missing" : outcome === "provider_binding_mismatch" ? "quarantined_binding_mismatch" : "quarantined_process_observation_unavailable",
6322
6339
  retryAfterMs: RETAINED_PROCESS_BINDING_QUARANTINE_RETRY_MS,
6323
6340
  quarantined: true
6324
6341
  };
@@ -6363,7 +6380,7 @@ async function captureRetainedProbeOutput(processId, result, capture) {
6363
6380
  await capture(pending.result, pending.chunkId);
6364
6381
  pendingRetainedProbeOutput.delete(processId);
6365
6382
  }
6366
- async function probeRetainedProcessAtProvider(settings, lease, process, mode = "observe", captureOutput) {
6383
+ async function probeRetainedProcessAtProvider(settings, lease, process, mode = "observe", captureOutput, providerPersistence) {
6367
6384
  if (lease.id !== process.leaseId || lease.sandboxGroupId !== process.sandboxGroupId || lease.leaseEpoch !== process.leaseEpoch || lease.backend !== process.providerBackend || lease.instanceId !== process.providerInstanceId || lease.resumeBackendId !== process.providerBackend || process.routeTargetId !== null) {
6368
6385
  return { status: "deferred", reason: "identity_mismatch" };
6369
6386
  }
@@ -6477,7 +6494,27 @@ async function probeRetainedProcessAtProvider(settings, lease, process, mode = "
6477
6494
  if (liveBinding.key !== process.providerBindingKey || configuredModalBinding?.key !== process.providerBindingKey) {
6478
6495
  return { status: "deferred", reason: "provider_binding_mismatch" };
6479
6496
  }
6497
+ const command = await providerPersistence?.load();
6498
+ if (!command || !providerPersistence || !session.bindProviderCommand)
6499
+ return { status: "deferred", reason: "process_observation_unavailable" };
6500
+ session.bindProviderCommand(process.providerSessionId, command, providerPersistence);
6480
6501
  }
6502
+ const capturePage = async (value) => {
6503
+ if (!captureOutput) {
6504
+ if (session.getProviderCommandOutput?.(value))
6505
+ throw new Error("Provider command output requires durable capture before settlement");
6506
+ return;
6507
+ }
6508
+ const page = session.getProviderCommandOutput?.(value);
6509
+ if (page) {
6510
+ for (const chunk of page.chunks)
6511
+ if (chunk.text)
6512
+ await captureOutput(chunk.text, chunk.chunkId, chunk.stream, page.streamFidelity);
6513
+ } else {
6514
+ await captureRetainedProbeOutput(process.id, value, captureOutput);
6515
+ }
6516
+ if (typeof value === "string") await session.acknowledgeCommandOutput?.(value);
6517
+ };
6481
6518
  let result;
6482
6519
  try {
6483
6520
  result = await withRetainedProcessProbeTimeout(
@@ -6492,7 +6529,7 @@ async function probeRetainedProcessAtProvider(settings, lease, process, mode = "
6492
6529
  if (error === RETAINED_PROCESS_PROBE_TIMEOUT) {
6493
6530
  return { status: "deferred", reason: "provider_timeout" };
6494
6531
  }
6495
- if (isProviderSandboxNotFoundError(client.backendId, error)) {
6532
+ if (isProviderSandboxGoneDuringRoutedOperation(client.backendId, error)) {
6496
6533
  if (process.providerBackend === "modal" && !process.providerBindingKey) {
6497
6534
  return { status: "deferred", reason: "provider_binding_missing" };
6498
6535
  }
@@ -6507,8 +6544,8 @@ async function probeRetainedProcessAtProvider(settings, lease, process, mode = "
6507
6544
  }
6508
6545
  return { status: "deferred", reason: "provider_error" };
6509
6546
  }
6510
- if (captureOutput) await captureRetainedProbeOutput(process.id, result, captureOutput);
6511
- const observation = classifyRetainedProcessPollResult(result, process.providerSessionId);
6547
+ await capturePage(result);
6548
+ const observation = classifyRetainedProcessPollResult(result, process.providerSessionId, session);
6512
6549
  if (observation.status === "deferred" && observation.reason === "provider_running" && lease.rotationRequestedAt !== null) {
6513
6550
  try {
6514
6551
  const interrupted = await withRetainedProcessProbeTimeout(
@@ -6519,10 +6556,10 @@ async function probeRetainedProcessAtProvider(settings, lease, process, mode = "
6519
6556
  maxOutputTokens: 2e3
6520
6557
  })
6521
6558
  );
6522
- if (captureOutput) await captureRetainedProbeOutput(process.id, interrupted, captureOutput);
6523
- return classifyRetainedProcessPollResult(interrupted, process.providerSessionId);
6559
+ await capturePage(interrupted);
6560
+ return classifyRetainedProcessPollResult(interrupted, process.providerSessionId, session);
6524
6561
  } catch (error) {
6525
- if (isProviderSandboxNotFoundError(client.backendId, error)) {
6562
+ if (isProviderSandboxGoneDuringRoutedOperation(client.backendId, error)) {
6526
6563
  if (process.providerBackend === "modal" && !process.providerBindingKey) {
6527
6564
  return { status: "deferred", reason: "provider_binding_missing" };
6528
6565
  }
@@ -6543,11 +6580,11 @@ async function probeRetainedProcessAtProvider(settings, lease, process, mode = "
6543
6580
  }
6544
6581
  return observation;
6545
6582
  }
6546
- function classifyRetainedProcessPollResult(result, providerSessionId) {
6583
+ function classifyRetainedProcessPollResult(result, providerSessionId, source) {
6547
6584
  if (typeof result !== "string") {
6548
6585
  return { status: "deferred", reason: "provider_unknown" };
6549
6586
  }
6550
- if (isExecSessionLostBanner(result, providerSessionId)) {
6587
+ if (isExecSessionLostBanner(result, providerSessionId, source)) {
6551
6588
  return {
6552
6589
  status: "proved",
6553
6590
  proof: {
@@ -6848,7 +6885,7 @@ async function terminateDrainableBox(db, settings, row, observability, terminate
6848
6885
  if (!lease) {
6849
6886
  return false;
6850
6887
  }
6851
- if (lease.liveness !== "draining" || lease.refcount !== 0 || lease.leaseEpoch !== row.leaseEpoch) {
6888
+ if (lease.liveness !== "draining" || lease.refcount !== 0 && !lease.unobservableCommandDrainIds?.length || lease.leaseEpoch !== row.leaseEpoch) {
6852
6889
  return false;
6853
6890
  }
6854
6891
  const durableBackendId = lease.resumeBackendId ?? lease.backend;
@@ -8294,6 +8331,7 @@ function createScheduledTaskActivities(services) {
8294
8331
  workspaceId: task.workspaceId,
8295
8332
  initialMessage: task.agentConfig.prompt,
8296
8333
  resources: task.agentConfig.resources,
8334
+ bundledSkillIds: task.agentConfig.bundledSkillIds,
8297
8335
  tools: taskTools,
8298
8336
  firstPartyMcpTools,
8299
8337
  firstPartyMcpPermissions,
@@ -9148,6 +9186,7 @@ async function recoverBoundScheduledTaskDispatch(input) {
9148
9186
  workspaceId: task.workspaceId,
9149
9187
  initialMessage: task.agentConfig.prompt,
9150
9188
  resources: task.agentConfig.resources,
9189
+ bundledSkillIds: task.agentConfig.bundledSkillIds,
9151
9190
  tools: input.acceptedExecution.resolvedTools,
9152
9191
  firstPartyMcpTools: input.acceptedExecution.resolvedFirstPartyMcpTools,
9153
9192
  firstPartyMcpPermissions: input.acceptedExecution.resolvedFirstPartyMcpPermissions,
@@ -10176,7 +10215,7 @@ function createWorkflowWakeActivities(services) {
10176
10215
  const timers = await listDueWorkspacePauseTimers(service.db, 100);
10177
10216
  for (const timer of timers) {
10178
10217
  try {
10179
- const result = await withWorkspaceRls(
10218
+ const result2 = await withWorkspaceRls(
10180
10219
  service.db,
10181
10220
  timer.workspace_id,
10182
10221
  (scoped) => scoped.transaction(
@@ -10186,11 +10225,11 @@ function createWorkflowWakeActivities(services) {
10186
10225
  })
10187
10226
  )
10188
10227
  );
10189
- if (result?.workspaceControlEventId) {
10228
+ if (result2?.workspaceControlEventId) {
10190
10229
  const event = await getWorkspaceControlEvent(
10191
10230
  service.db,
10192
10231
  timer.workspace_id,
10193
- result.workspaceControlEventId
10232
+ result2.workspaceControlEventId
10194
10233
  );
10195
10234
  if (event)
10196
10235
  await publishDurableWorkspaceControlEvent(service.bus, timer.workspace_id, event);
@@ -10203,6 +10242,10 @@ function createWorkflowWakeActivities(services) {
10203
10242
  }
10204
10243
  }
10205
10244
  let claimed = 0;
10245
+ let signaled = 0;
10246
+ let pendingAdmission = 0;
10247
+ let unconfirmed = 0;
10248
+ const pendingAdmissionBlockers = {};
10206
10249
  let delivered = 0;
10207
10250
  let failed = 0;
10208
10251
  let exhaustedBatchLimit = false;
@@ -10215,7 +10258,14 @@ function createWorkflowWakeActivities(services) {
10215
10258
  const limit = Math.min(BATCH_SIZE, remaining);
10216
10259
  const batch = await reconcilePendingSessionWorkflowWakes(service, limit);
10217
10260
  claimed += batch.claimed;
10261
+ signaled += batch.signaled;
10218
10262
  delivered += batch.delivered;
10263
+ pendingAdmission += batch.pendingAdmission;
10264
+ unconfirmed += batch.unconfirmed;
10265
+ for (const [blocker, count] of Object.entries(batch.pendingAdmissionBlockers)) {
10266
+ const key = blocker;
10267
+ pendingAdmissionBlockers[key] = (pendingAdmissionBlockers[key] ?? 0) + count;
10268
+ }
10219
10269
  failed += batch.failed;
10220
10270
  if (batch.claimed < limit) break;
10221
10271
  }
@@ -10230,7 +10280,34 @@ function createWorkflowWakeActivities(services) {
10230
10280
  failed: titleFanout.failed
10231
10281
  });
10232
10282
  }
10233
- return { claimed, delivered, failed, exhaustedBatchLimit };
10283
+ const result = {
10284
+ claimed,
10285
+ signaled,
10286
+ delivered,
10287
+ pendingAdmission,
10288
+ unconfirmed,
10289
+ failed,
10290
+ pendingAdmissionBlockers,
10291
+ exhaustedBatchLimit
10292
+ };
10293
+ if (claimed > 0) {
10294
+ service.observability.info("session workflow wake delivery reconciled", {
10295
+ claimed,
10296
+ signaled,
10297
+ delivered,
10298
+ pendingAdmission,
10299
+ unconfirmed,
10300
+ failed,
10301
+ exhaustedBatchLimit,
10302
+ ...Object.fromEntries(
10303
+ Object.entries(pendingAdmissionBlockers).map(([blocker, count]) => [
10304
+ `pendingAdmissionBlockers.${blocker}`,
10305
+ count
10306
+ ])
10307
+ )
10308
+ });
10309
+ }
10310
+ return result;
10234
10311
  }
10235
10312
  };
10236
10313
  }
@@ -10273,4 +10350,4 @@ export {
10273
10350
  createControlActivities,
10274
10351
  createControlActivitiesFromServices
10275
10352
  };
10276
- //# sourceMappingURL=activities-control-VMA3XMHE.js.map
10353
+ //# sourceMappingURL=activities-control-WZRFEIJH.js.map