bopodev-api 0.1.32 → 0.1.34

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.
@@ -9,6 +9,7 @@ import {
9
9
  ControlPlaneRequestHeadersSchema,
10
10
  ControlPlaneRuntimeEnvSchema,
11
11
  ExecutionOutcomeSchema,
12
+ mergeBuiltinSkillIdsForInjection,
12
13
  type ExecutionOutcome,
13
14
  type RunArtifact,
14
15
  type RunCompletionReason,
@@ -59,6 +60,7 @@ import { createHeartbeatRunsRealtimeEvent, loadHeartbeatRunsRealtimeSnapshot } f
59
60
  import { publishAttentionSnapshot } from "../../realtime/attention";
60
61
  import { publishOfficeOccupantForAgent } from "../../realtime/office-space";
61
62
  import { appendProjectBudgetUsage, checkAgentBudget, checkProjectBudget } from "../budget-service";
63
+ import { materializeLinkedSkillsForRuntime } from "../company-skill-file-service";
62
64
  import { appendDurableFact, loadAgentMemoryContext, persistHeartbeatMemory } from "../memory-file-service";
63
65
  import { calculateModelPricedUsdCost } from "../model-pricing";
64
66
  import { runPluginHook } from "../plugin-runtime";
@@ -527,6 +529,7 @@ export async function runHeartbeatForAgent(
527
529
  let transcriptLiveHighSignalCount = 0;
528
530
  let transcriptPersistFailureReported = false;
529
531
  let pluginFailureSummary: string[] = [];
532
+ let linkedSkillsMaterializationCleanup: (() => Promise<void>) | null = null;
530
533
  const seenResultMessages = new Set<string>();
531
534
  const runDigestSignals: RunDigestSignal[] = [];
532
535
 
@@ -706,13 +709,24 @@ export async function runHeartbeatForAgent(
706
709
  if (runMode === "redo") {
707
710
  state = clearResumeState(state);
708
711
  }
709
- const heartbeatRuntimeEnv = buildHeartbeatRuntimeEnv({
710
- companyId,
711
- agentId: agent.id,
712
- heartbeatRunId: runId,
713
- canHireAgents: agent.canHireAgents,
714
- wakeContext: options?.wakeContext
712
+ const mergedSkillIds = mergeRuntimeForExecution(
713
+ { enabledSkillIds: persistedRuntime.enabledSkillIds },
714
+ state.runtime
715
+ ).enabledSkillIds;
716
+ const linkedMaterialized = await materializeLinkedSkillsForRuntime(companyId, {
717
+ enabledSkillIds: mergedSkillIds
715
718
  });
719
+ linkedSkillsMaterializationCleanup = linkedMaterialized.cleanup;
720
+ const heartbeatRuntimeEnv: Record<string, string> = {
721
+ ...buildHeartbeatRuntimeEnv({
722
+ companyId,
723
+ agentId: agent.id,
724
+ heartbeatRunId: runId,
725
+ canHireAgents: agent.canHireAgents,
726
+ wakeContext: options?.wakeContext
727
+ }),
728
+ ...(linkedMaterialized.root ? { BOPODEV_MATERIALIZED_LINKED_SKILLS_ROOT: linkedMaterialized.root } : {})
729
+ };
716
730
  const runtimeFromConfig = {
717
731
  command: persistedRuntime.runtimeCommand,
718
732
  args: persistedRuntime.runtimeArgs,
@@ -745,15 +759,27 @@ export async function runHeartbeatForAgent(
745
759
  thinkingEffort: persistedRuntime.runtimeThinkingEffort,
746
760
  bootstrapPrompt: persistedRuntime.bootstrapPrompt,
747
761
  interruptGraceSec: persistedRuntime.interruptGraceSec,
748
- runPolicy: persistedRuntime.runPolicy
762
+ runPolicy: persistedRuntime.runPolicy,
763
+ enabledSkillIds: persistedRuntime.enabledSkillIds
749
764
  };
750
765
  const mergedRuntime = mergeRuntimeForExecution(runtimeFromConfig, state.runtime);
766
+ const runtimeForWorkspace = {
767
+ ...mergedRuntime,
768
+ env: {
769
+ ...(mergedRuntime.env ?? {}),
770
+ ...(mergedRuntime.enabledSkillIds !== undefined
771
+ ? {
772
+ BOPODEV_ENABLED_SKILL_IDS: mergeBuiltinSkillIdsForInjection(mergedRuntime.enabledSkillIds)!.join(",")
773
+ }
774
+ : {})
775
+ }
776
+ };
751
777
  const workspaceResolution = await resolveRuntimeWorkspaceForWorkItems(
752
778
  db,
753
779
  companyId,
754
780
  agent.id,
755
781
  contextWorkItems,
756
- mergedRuntime
782
+ runtimeForWorkspace
757
783
  );
758
784
  await mkdir(join(resolveAgentFallbackWorkspace(companyId, agent.id), "operating"), { recursive: true });
759
785
  state = {
@@ -1735,6 +1761,14 @@ export async function runHeartbeatForAgent(
1735
1761
  });
1736
1762
  }
1737
1763
  } finally {
1764
+ if (linkedSkillsMaterializationCleanup) {
1765
+ try {
1766
+ await linkedSkillsMaterializationCleanup();
1767
+ } catch {
1768
+ // Best effort: linked skill temp dir cleanup should not mask heartbeat teardown.
1769
+ }
1770
+ linkedSkillsMaterializationCleanup = null;
1771
+ }
1738
1772
  await transcriptWriteQueue;
1739
1773
  if (discardIdleNoWorkRunAfterFlush) {
1740
1774
  try {
@@ -3380,6 +3414,7 @@ function parseAgentState(stateBlob: string | null) {
3380
3414
  model?: string;
3381
3415
  thinkingEffort?: "auto" | "low" | "medium" | "high";
3382
3416
  bootstrapPrompt?: string;
3417
+ enabledSkillIds?: string[];
3383
3418
  runPolicy?: {
3384
3419
  sandboxMode?: "workspace_write" | "full_access";
3385
3420
  allowWebSearch?: boolean;
@@ -3924,6 +3959,7 @@ function mergeRuntimeForExecution(
3924
3959
  model?: string;
3925
3960
  thinkingEffort?: "auto" | "low" | "medium" | "high";
3926
3961
  bootstrapPrompt?: string;
3962
+ enabledSkillIds?: string[];
3927
3963
  runPolicy?: {
3928
3964
  sandboxMode?: "workspace_write" | "full_access";
3929
3965
  allowWebSearch?: boolean;
@@ -3943,6 +3979,7 @@ function mergeRuntimeForExecution(
3943
3979
  model?: string;
3944
3980
  thinkingEffort?: "auto" | "low" | "medium" | "high";
3945
3981
  bootstrapPrompt?: string;
3982
+ enabledSkillIds?: string[];
3946
3983
  runPolicy?: {
3947
3984
  sandboxMode?: "workspace_write" | "full_access";
3948
3985
  allowWebSearch?: boolean;