@sema-agent/core 1.298.0 → 1.299.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.
@@ -1,6 +1,6 @@
1
1
  import { AgentHarness, DEFAULT_COMPACTION_SETTINGS, uuidv7 } from "../../internal/harness.js";
2
2
  import { CheckpointError, BINDING_CHECKPOINT_VERSION, checkpointVersionOf, MAX_SUPPORTED_CHECKPOINT_VERSION, remainingBudgetMicroUsd, validatePendingSteer, winnerFromOutcome, } from "../checkpoint-store.js";
3
- import { effectiveCushionMs, estimateCycleMs, minLiveWriteoutWindowMs, recordCallSample, recordToolSample, recordTtftSample, softExecDeadlineMs, writeoutCushionMs } from "./call-cap.js";
3
+ import { effectiveCushionMs, estimateCycleMs, hasRealContent, minLiveWriteoutWindowMs, recordCallSample, recordToolCycleSample, recordToolSample, recordTtftSample, softExecDeadlineMs, writeoutCushionMs } from "./call-cap.js";
4
4
  import { engineVersion } from "../version.js";
5
5
  import { DEFAULT_COMPACTION_INSTRUCTIONS, createRapidRefillState, isCompactionManualCancel, isCompactionWalltimeAbort, maybeCompact, nextTrimForceBackoff, recordCompactionAndCheckRapidRefill } from "../auto-compaction.js";
6
6
  import { ASK_USER_QUESTION_TOOL_NAME } from "../ask-question.js";
@@ -23,7 +23,7 @@ import { toImageContent } from "./image.js";
23
23
  import { OUTPUT_TOOL_NAME, resolveOutputRetries } from "./synthetic-tools.js";
24
24
  import { cacheFamilyOf, usageCostMicroUsd } from "./usage-accounting.js";
25
25
  import { assembleResult, errorCodeOf } from "./assemble-result.js";
26
- import { ATTACHMENT_BYTE_CAP, CHANGED_FILES_MAX, advanceCadenceClock, agentListingDeltaHeader, agentListingInitialHeader, collectDueAttachments, commitAgentListing, createAttachmentState, rebaseCadenceWindows, reduceToolEnd, renderAgentListingDelta, renderMcpInstructionsDelta, renderOrphanedBackgroundTasks, renderToolsDelta, stampWriteAnchor } from "./turn-attachments.js";
26
+ import { ATTACHMENT_BYTE_CAP, CHANGED_FILES_MAX, advanceCadenceClock, agentListingDeltaHeader, agentListingInitialHeader, collectDateChange, collectDueAttachments, commitAgentListing, createAttachmentState, rebaseCadenceWindows, reduceToolEnd, renderAgentListingDelta, renderMcpInstructionsDelta, renderOrphanedBackgroundTasks, renderToolsDelta, stampWriteAnchor } from "./turn-attachments.js";
27
27
  import { prepareTask } from "./prepare-task.js";
28
28
  import { hasVerifiableStructureSignal } from "./grounding-signal.js";
29
29
  import { hasDestroy, isIsolated } from "../remote-env.js";
@@ -806,6 +806,7 @@ export class Runner {
806
806
  let groundingSignalPostR9 = false;
807
807
  const attachmentsCfg = spec.attachments;
808
808
  const attachState = attachmentsCfg !== undefined ? createAttachmentState() : undefined;
809
+ const dateState = prepared.dateChange !== undefined ? { announcedDate: prepared.dateChange.legDate } : undefined;
809
810
  let cadenceTurns = 0;
810
811
  let lastTurnHadToolCalls = false;
811
812
  if (attachState !== undefined && attachmentsCfg?.backgroundTasks === true) {
@@ -889,6 +890,7 @@ export class Runner {
889
890
  }
890
891
  const writeFamilyOf = (name) => writeFamilyByName.get(name) ?? writeFamilyOfCanonical(canonicalToolName(name));
891
892
  const toolStartAt = new Map();
893
+ const turnToolSpan = {};
892
894
  const startedToolCallIds = new Set();
893
895
  emitTrace(tracer, () => ({ kind: "task.start", version: 1, taskId, model: prepared.model.id, engineVersion: engineVersion(), ts: taskStart }));
894
896
  emitTrace(tracer, () => ({
@@ -1108,7 +1110,9 @@ export class Runner {
1108
1110
  prepared.callIssuedAtRef.current = undefined;
1109
1111
  const capLast = prepared.callCapRef?.state.last;
1110
1112
  if (prepared.callCapRef) {
1111
- recordCallSample(prepared.callCapRef.state, u.output || 0, callStartAt !== undefined ? callEndAt - callStartAt : 0);
1113
+ recordCallSample(prepared.callCapRef.state, u.output || 0, callStartAt !== undefined ? callEndAt - callStartAt : 0, {
1114
+ contentValid: m.usageMissing === true && hasRealContent(m.content),
1115
+ });
1112
1116
  if (callStartAt !== undefined && firstTokenAt !== undefined) {
1113
1117
  recordTtftSample(prepared.callCapRef.state, firstTokenAt - callStartAt);
1114
1118
  }
@@ -1213,9 +1217,10 @@ export class Runner {
1213
1217
  m.content.some((c) => c?.type === "thinking")) {
1214
1218
  prepared.callCapRef.reasoningObserved = true;
1215
1219
  }
1216
- if (attachState !== undefined && m.role === "assistant") {
1220
+ if (m.role === "assistant") {
1217
1221
  const content = m.content;
1218
- cadenceTurns = advanceCadenceClock(attachState, cadenceTurns, content, writeFamilyOf);
1222
+ if (attachState !== undefined)
1223
+ cadenceTurns = advanceCadenceClock(attachState, cadenceTurns, content, writeFamilyOf);
1219
1224
  lastTurnHadToolCalls = Array.isArray(content) && content.some((c) => c?.type === "toolCall");
1220
1225
  }
1221
1226
  callStartAt = undefined;
@@ -1256,6 +1261,8 @@ export class Runner {
1256
1261
  const toolNow = Date.now();
1257
1262
  if (prepared.callCapRef && toolStarted !== undefined) {
1258
1263
  recordToolSample(prepared.callCapRef.state, toolNow - toolStarted);
1264
+ turnToolSpan.startMin = turnToolSpan.startMin === undefined ? toolStarted : Math.min(turnToolSpan.startMin, toolStarted);
1265
+ turnToolSpan.endMax = turnToolSpan.endMax === undefined ? toolNow : Math.max(turnToolSpan.endMax, toolNow);
1259
1266
  }
1260
1267
  if (!wroteThisRun && (prepared.toolEffects.get(event.toolName) ?? "write") !== "read") {
1261
1268
  wroteThisRun = true;
@@ -1683,6 +1690,11 @@ export class Runner {
1683
1690
  w.resolve(outcome);
1684
1691
  };
1685
1692
  const onTurnBoundary = async (event) => {
1693
+ if (prepared.callCapRef && turnToolSpan.startMin !== undefined && turnToolSpan.endMax !== undefined) {
1694
+ recordToolCycleSample(prepared.callCapRef.state, turnToolSpan.endMax - turnToolSpan.startMin);
1695
+ }
1696
+ turnToolSpan.startMin = undefined;
1697
+ turnToolSpan.endMax = undefined;
1686
1698
  let boundarySteered = false;
1687
1699
  if (prepared.suspendForResource === undefined) {
1688
1700
  const nowMs = Date.now();
@@ -1763,87 +1775,97 @@ export class Runner {
1763
1775
  }
1764
1776
  let boundaryAttachmentBytes = 0;
1765
1777
  let attachmentsPayload;
1766
- if (attachState !== undefined &&
1767
- attachmentsCfg !== undefined &&
1778
+ if ((dateState !== undefined || (attachState !== undefined && attachmentsCfg !== undefined)) &&
1768
1779
  !boundarySteered &&
1769
1780
  !finalizeInjected &&
1770
1781
  finalVerifyInjections === 0 &&
1771
1782
  !prepared.abortController.signal.aborted) {
1772
- const changedFilesOn = Boolean(attachmentsCfg.changedFiles);
1773
- let changed;
1774
- if (changedFilesOn && prepared.detectExternalChanges !== undefined) {
1775
- const maxFiles = typeof attachmentsCfg.changedFiles === "object"
1776
- ? (attachmentsCfg.changedFiles.maxFiles ?? CHANGED_FILES_MAX)
1777
- : CHANGED_FILES_MAX;
1778
- const SCAN_CEILING_MS = 2_000;
1779
- const scan = await Promise.race([
1780
- prepared.detectExternalChanges(maxFiles),
1781
- new Promise((resolve) => {
1782
- const t = setTimeout(() => resolve({ changed: [], evicted: [] }), SCAN_CEILING_MS);
1783
- t.unref?.();
1784
- }),
1785
- ]);
1786
- for (const p of scan.evicted)
1787
- attachState.surfacedMtime.delete(p);
1788
- changed = scan.changed;
1789
- }
1790
- const backgroundTasksOn = attachmentsCfg.backgroundTasks === true;
1791
- const bgTasks = backgroundTasksOn && attachState.postCompactPending ? prepared.listBackgroundTasks() : undefined;
1792
- const toolsDeltaOn = attachmentsCfg.toolsDelta === true;
1793
- const pendingTools = toolsDeltaOn && prepared.toolsDeltaRef !== undefined && prepared.toolsDeltaRef.pending.length > 0
1794
- ? [...prepared.toolsDeltaRef.pending]
1795
- : undefined;
1796
- const agentListingOn = attachmentsCfg.agentListing === true;
1797
- const mcpInstructionsOn = attachmentsCfg.mcpInstructions === true;
1798
- const mcpDelta = prepared.mcp.instructionsDelta;
1799
- const mcpAdds = mcpInstructionsOn && mcpDelta.pendingAdds.length > 0 ? [...mcpDelta.pendingAdds] : undefined;
1800
- const mcpRemovals = mcpInstructionsOn && mcpDelta.pendingRemovals.length > 0 ? [...mcpDelta.pendingRemovals] : undefined;
1801
- const budgetUsdOn = attachmentsCfg.budgetUsd === true && maxCostMicroUsd !== undefined && lastTurnHadToolCalls;
1802
- const due = collectDueAttachments(attachState, {
1803
- turn: stats.turns,
1804
- cadenceTurn: cadenceTurns,
1805
- todoMounted: todoToolMounted,
1806
- taskListMounted: taskToolsMounted,
1807
- planActive: prepared.planModeRef.active,
1808
- config: {
1809
- todoReminder: attachmentsCfg.todoReminder === true,
1810
- ...(attachmentsCfg.todoReminderMode !== undefined ? { todoReminderMode: attachmentsCfg.todoReminderMode } : {}),
1811
- changedFiles: changedFilesOn,
1812
- planModeReminder: attachmentsCfg.planModeReminder === true,
1813
- budgetUsd: budgetUsdOn,
1814
- backgroundTasks: backgroundTasksOn,
1815
- toolsDelta: toolsDeltaOn,
1816
- agentListing: agentListingOn,
1817
- mcpInstructions: mcpInstructionsOn,
1818
- },
1819
- ...(changed !== undefined ? { changedFiles: changed } : {}),
1820
- ...(budgetUsdOn && maxCostMicroUsd !== undefined
1821
- ? { budgetUsd: { used: stats.costMicroUsd / 1e6, total: maxCostMicroUsd / 1e6 } }
1822
- : {}),
1823
- ...(bgTasks !== undefined ? { backgroundTasks: bgTasks } : {}),
1824
- ...(pendingTools !== undefined ? { newTools: pendingTools } : {}),
1825
- ...(agentListingOn && prepared.agentListing !== undefined
1826
- ? { agentListing: prepared.agentListing.entries, agentToolName: prepared.agentListing.toolName }
1827
- : {}),
1828
- ...(mcpAdds !== undefined || mcpRemovals !== undefined
1829
- ? { mcpInstructions: { added: mcpAdds ?? [], removed: mcpRemovals ?? [] } }
1830
- : {}),
1831
- });
1832
- if (pendingTools !== undefined && due.some((a) => a.source === "tools_delta" && a.body === renderToolsDelta(pendingTools))) {
1833
- prepared.toolsDeltaRef.pending.splice(0, pendingTools.length);
1834
- }
1835
- if ((mcpAdds !== undefined || mcpRemovals !== undefined) &&
1836
- due.some((a) => a.source === "mcp_instructions" && a.body === renderMcpInstructionsDelta(mcpAdds ?? [], mcpRemovals ?? []))) {
1837
- if (mcpAdds !== undefined)
1838
- mcpDelta.pendingAdds.splice(0, mcpAdds.length);
1839
- if (mcpRemovals !== undefined)
1840
- mcpDelta.pendingRemovals.splice(0, mcpRemovals.length);
1841
- }
1842
- if (agentListingOn && prepared.agentListing !== undefined && due.some((a) => a.source === "agent_listing")) {
1843
- const listing = prepared.agentListing;
1844
- const intactBody = renderAgentListingDelta(attachState, listing.entries, listing.toolName);
1845
- if (intactBody !== undefined && due.some((a) => a.source === "agent_listing" && a.body === intactBody)) {
1846
- commitAgentListing(attachState, listing.entries);
1783
+ const due = [];
1784
+ if (attachState !== undefined && attachmentsCfg !== undefined) {
1785
+ const changedFilesOn = Boolean(attachmentsCfg.changedFiles);
1786
+ let changed;
1787
+ if (changedFilesOn && prepared.detectExternalChanges !== undefined) {
1788
+ const maxFiles = typeof attachmentsCfg.changedFiles === "object"
1789
+ ? (attachmentsCfg.changedFiles.maxFiles ?? CHANGED_FILES_MAX)
1790
+ : CHANGED_FILES_MAX;
1791
+ const SCAN_CEILING_MS = 2_000;
1792
+ const scan = await Promise.race([
1793
+ prepared.detectExternalChanges(maxFiles),
1794
+ new Promise((resolve) => {
1795
+ const t = setTimeout(() => resolve({ changed: [], evicted: [] }), SCAN_CEILING_MS);
1796
+ t.unref?.();
1797
+ }),
1798
+ ]);
1799
+ for (const p of scan.evicted)
1800
+ attachState.surfacedMtime.delete(p);
1801
+ changed = scan.changed;
1802
+ }
1803
+ const backgroundTasksOn = attachmentsCfg.backgroundTasks === true;
1804
+ const bgTasks = backgroundTasksOn && attachState.postCompactPending ? prepared.listBackgroundTasks() : undefined;
1805
+ const toolsDeltaOn = attachmentsCfg.toolsDelta === true;
1806
+ const pendingTools = toolsDeltaOn && prepared.toolsDeltaRef !== undefined && prepared.toolsDeltaRef.pending.length > 0
1807
+ ? [...prepared.toolsDeltaRef.pending]
1808
+ : undefined;
1809
+ const agentListingOn = attachmentsCfg.agentListing === true;
1810
+ const mcpInstructionsOn = attachmentsCfg.mcpInstructions === true;
1811
+ const mcpDelta = prepared.mcp.instructionsDelta;
1812
+ const mcpAdds = mcpInstructionsOn && mcpDelta.pendingAdds.length > 0 ? [...mcpDelta.pendingAdds] : undefined;
1813
+ const mcpRemovals = mcpInstructionsOn && mcpDelta.pendingRemovals.length > 0 ? [...mcpDelta.pendingRemovals] : undefined;
1814
+ const budgetUsdOn = attachmentsCfg.budgetUsd === true && maxCostMicroUsd !== undefined && lastTurnHadToolCalls;
1815
+ due.push(...collectDueAttachments(attachState, {
1816
+ turn: stats.turns,
1817
+ cadenceTurn: cadenceTurns,
1818
+ todoMounted: todoToolMounted,
1819
+ taskListMounted: taskToolsMounted,
1820
+ planActive: prepared.planModeRef.active,
1821
+ config: {
1822
+ todoReminder: attachmentsCfg.todoReminder === true,
1823
+ ...(attachmentsCfg.todoReminderMode !== undefined ? { todoReminderMode: attachmentsCfg.todoReminderMode } : {}),
1824
+ changedFiles: changedFilesOn,
1825
+ planModeReminder: attachmentsCfg.planModeReminder === true,
1826
+ budgetUsd: budgetUsdOn,
1827
+ backgroundTasks: backgroundTasksOn,
1828
+ toolsDelta: toolsDeltaOn,
1829
+ agentListing: agentListingOn,
1830
+ mcpInstructions: mcpInstructionsOn,
1831
+ },
1832
+ ...(changed !== undefined ? { changedFiles: changed } : {}),
1833
+ ...(budgetUsdOn && maxCostMicroUsd !== undefined
1834
+ ? { budgetUsd: { used: stats.costMicroUsd / 1e6, total: maxCostMicroUsd / 1e6 } }
1835
+ : {}),
1836
+ ...(bgTasks !== undefined ? { backgroundTasks: bgTasks } : {}),
1837
+ ...(pendingTools !== undefined ? { newTools: pendingTools } : {}),
1838
+ ...(agentListingOn && prepared.agentListing !== undefined
1839
+ ? { agentListing: prepared.agentListing.entries, agentToolName: prepared.agentListing.toolName }
1840
+ : {}),
1841
+ ...(mcpAdds !== undefined || mcpRemovals !== undefined
1842
+ ? { mcpInstructions: { added: mcpAdds ?? [], removed: mcpRemovals ?? [] } }
1843
+ : {}),
1844
+ }));
1845
+ if (pendingTools !== undefined && due.some((a) => a.source === "tools_delta" && a.body === renderToolsDelta(pendingTools))) {
1846
+ prepared.toolsDeltaRef.pending.splice(0, pendingTools.length);
1847
+ }
1848
+ if ((mcpAdds !== undefined || mcpRemovals !== undefined) &&
1849
+ due.some((a) => a.source === "mcp_instructions" && a.body === renderMcpInstructionsDelta(mcpAdds ?? [], mcpRemovals ?? []))) {
1850
+ if (mcpAdds !== undefined)
1851
+ mcpDelta.pendingAdds.splice(0, mcpAdds.length);
1852
+ if (mcpRemovals !== undefined)
1853
+ mcpDelta.pendingRemovals.splice(0, mcpRemovals.length);
1854
+ }
1855
+ if (agentListingOn && prepared.agentListing !== undefined && due.some((a) => a.source === "agent_listing")) {
1856
+ const listing = prepared.agentListing;
1857
+ const intactBody = renderAgentListingDelta(attachState, listing.entries, listing.toolName);
1858
+ if (intactBody !== undefined && due.some((a) => a.source === "agent_listing" && a.body === intactBody)) {
1859
+ commitAgentListing(attachState, listing.entries);
1860
+ }
1861
+ }
1862
+ }
1863
+ if (dateState !== undefined && lastTurnHadToolCalls) {
1864
+ const today = prepared.dateChange.today();
1865
+ const cand = collectDateChange(dateState, today);
1866
+ if (cand !== undefined) {
1867
+ due.unshift(cand);
1868
+ dateState.announcedDate = today;
1847
1869
  }
1848
1870
  }
1849
1871
  if (due.length > 0) {