@sema-agent/core 1.279.0 → 1.281.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 (87) hide show
  1. package/dist/agents/subagent.d.ts +12 -0
  2. package/dist/agents/subagent.d.ts.map +1 -1
  3. package/dist/agents/subagent.js +221 -19
  4. package/dist/agents/subagent.js.map +1 -1
  5. package/dist/bin/sema-tb.d.ts +10 -0
  6. package/dist/bin/sema-tb.d.ts.map +1 -1
  7. package/dist/bin/sema-tb.js +81 -10
  8. package/dist/bin/sema-tb.js.map +1 -1
  9. package/dist/core/background-shell.d.ts +2 -0
  10. package/dist/core/background-shell.d.ts.map +1 -1
  11. package/dist/core/background-shell.js.map +1 -1
  12. package/dist/core/context-guard.d.ts +2 -0
  13. package/dist/core/context-guard.d.ts.map +1 -1
  14. package/dist/core/context-guard.js +10 -0
  15. package/dist/core/context-guard.js.map +1 -1
  16. package/dist/core/mcp.d.ts +4 -0
  17. package/dist/core/mcp.d.ts.map +1 -1
  18. package/dist/core/mcp.js +189 -32
  19. package/dist/core/mcp.js.map +1 -1
  20. package/dist/core/runner/assemble-result.d.ts +2 -0
  21. package/dist/core/runner/assemble-result.d.ts.map +1 -1
  22. package/dist/core/runner/assemble-result.js.map +1 -1
  23. package/dist/core/runner/call-cap.d.ts +10 -0
  24. package/dist/core/runner/call-cap.d.ts.map +1 -1
  25. package/dist/core/runner/call-cap.js +27 -1
  26. package/dist/core/runner/call-cap.js.map +1 -1
  27. package/dist/core/runner/prepare-task.d.ts.map +1 -1
  28. package/dist/core/runner/prepare-task.js +20 -4
  29. package/dist/core/runner/prepare-task.js.map +1 -1
  30. package/dist/core/runner/runtask.d.ts.map +1 -1
  31. package/dist/core/runner/runtask.js +66 -24
  32. package/dist/core/runner/runtask.js.map +1 -1
  33. package/dist/core/session-reconcile.d.ts +1 -1
  34. package/dist/core/session-reconcile.d.ts.map +1 -1
  35. package/dist/core/session-reconcile.js +7 -2
  36. package/dist/core/session-reconcile.js.map +1 -1
  37. package/dist/core/task-notification.d.ts +2 -0
  38. package/dist/core/task-notification.d.ts.map +1 -1
  39. package/dist/core/task-notification.js.map +1 -1
  40. package/dist/core/task-registry.d.ts +1 -0
  41. package/dist/core/task-registry.d.ts.map +1 -1
  42. package/dist/core/task-registry.js +184 -55
  43. package/dist/core/task-registry.js.map +1 -1
  44. package/dist/core/types.d.ts +2 -0
  45. package/dist/core/types.d.ts.map +1 -1
  46. package/dist/engine/execution-env/node-execution-env.d.ts.map +1 -1
  47. package/dist/engine/execution-env/node-execution-env.js +17 -0
  48. package/dist/engine/execution-env/node-execution-env.js.map +1 -1
  49. package/dist/engine/harness/agent-harness.d.ts +1 -0
  50. package/dist/engine/harness/agent-harness.d.ts.map +1 -1
  51. package/dist/engine/harness/agent-harness.js +3 -0
  52. package/dist/engine/harness/agent-harness.js.map +1 -1
  53. package/dist/engine/harness/types.d.ts +8 -0
  54. package/dist/engine/harness/types.d.ts.map +1 -1
  55. package/dist/engine/harness/types.js.map +1 -1
  56. package/dist/engine/loop/agent-loop.js +163 -35
  57. package/dist/engine/loop/agent-loop.js.map +1 -1
  58. package/dist/engine/loop/types.d.ts +8 -0
  59. package/dist/engine/loop/types.d.ts.map +1 -1
  60. package/dist/index.d.ts +1 -1
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +1 -1
  63. package/dist/index.js.map +1 -1
  64. package/dist/orchestration/workflow.d.ts +19 -3
  65. package/dist/orchestration/workflow.d.ts.map +1 -1
  66. package/dist/orchestration/workflow.js +61 -11
  67. package/dist/orchestration/workflow.js.map +1 -1
  68. package/dist/tools/fs/index.d.ts +1 -0
  69. package/dist/tools/fs/index.d.ts.map +1 -1
  70. package/dist/tools/fs/index.js +137 -35
  71. package/dist/tools/fs/index.js.map +1 -1
  72. package/dist/tools/fs/pdf.d.ts +5 -0
  73. package/dist/tools/fs/pdf.d.ts.map +1 -1
  74. package/dist/tools/fs/pdf.js +58 -11
  75. package/dist/tools/fs/pdf.js.map +1 -1
  76. package/dist/tools/fs/safety.d.ts +1 -0
  77. package/dist/tools/fs/safety.d.ts.map +1 -1
  78. package/dist/tools/fs/safety.js +1 -0
  79. package/dist/tools/fs/safety.js.map +1 -1
  80. package/dist/tools/fs/search.d.ts +13 -0
  81. package/dist/tools/fs/search.d.ts.map +1 -1
  82. package/dist/tools/fs/search.js +58 -16
  83. package/dist/tools/fs/search.js.map +1 -1
  84. package/dist/tools/web.d.ts.map +1 -1
  85. package/dist/tools/web.js +141 -28
  86. package/dist/tools/web.js.map +1 -1
  87. package/package.json +2 -2
@@ -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, winnerFromOutcome, } from "../checkpoint-store.js";
3
- import { estimateCycleMs, recordCallSample, recordToolSample, writeoutCushionMs } from "./call-cap.js";
3
+ import { effectiveCushionMs, estimateCycleMs, recordCallSample, recordToolSample, writeoutCushionMs } from "./call-cap.js";
4
4
  import { DEFAULT_COMPACTION_INSTRUCTIONS, createRapidRefillState, maybeCompact, nextTrimForceBackoff, recordCompactionAndCheckRapidRefill } from "../auto-compaction.js";
5
5
  import { ASK_USER_QUESTION_TOOL_NAME } from "../ask-question.js";
6
6
  import { computeCostMicroUsd, modelCostToPricing } from "../pricing.js";
@@ -300,6 +300,8 @@ export class Runner {
300
300
  for (const w of manualCompactRef.waiters.splice(0))
301
301
  w(outcome);
302
302
  };
303
+ const runStartedAt = Date.now();
304
+ const taskIdRef = { current: spec.taskId };
303
305
  const run = (async () => {
304
306
  const releaseLock = spec.sessionId
305
307
  ? await this.acquireSessionLock(spec.sessionId)
@@ -316,7 +318,7 @@ export class Runner {
316
318
  publishReady(h);
317
319
  }, (s) => {
318
320
  reapHandle = s;
319
- }, manualCompactRef, resume, { ...(internals ?? {}), detachHub });
321
+ }, manualCompactRef, taskIdRef, resume, { ...(internals ?? {}), detachHub });
320
322
  }
321
323
  finally {
322
324
  releaseLock?.();
@@ -346,8 +348,17 @@ export class Runner {
346
348
  catch {
347
349
  }
348
350
  }
351
+ if (resultValue !== undefined) {
352
+ try {
353
+ this.deps.onError?.(err instanceof Error ? err : new Error(String(err)), { phase: "config", sessionId: resultValue.sessionId });
354
+ }
355
+ catch {
356
+ }
357
+ queue.close();
358
+ return;
359
+ }
349
360
  resultValue = {
350
- taskId: spec.taskId ?? "unknown",
361
+ taskId: taskIdRef.current ?? "unknown",
351
362
  sessionId: spec.sessionId ?? "unknown",
352
363
  status: "failed",
353
364
  result: "",
@@ -355,6 +366,17 @@ export class Runner {
355
366
  errorCode: code,
356
367
  stats: { turns: 0, tokens: 0, toolCalls: 0, cachedTokens: 0, costUsd: 0 },
357
368
  };
369
+ emitTrace(spec.tracer ?? this.deps.tracer, () => ({
370
+ kind: "task.end",
371
+ version: 1,
372
+ taskId: taskIdRef.current ?? "unknown",
373
+ status: "failed",
374
+ errorCode: code,
375
+ turns: 0,
376
+ tokens: 0,
377
+ durationMs: Date.now() - runStartedAt,
378
+ ts: Date.now(),
379
+ }));
358
380
  queue.push({ type: "done", result: resultValue });
359
381
  queue.close();
360
382
  });
@@ -460,7 +482,7 @@ export class Runner {
460
482
  })()),
461
483
  };
462
484
  }
463
- async runLocked(spec, queue, setResult, onConsolidation, onSuggestions, onReady, onSuspend, manualCompactRef, resume, internals) {
485
+ async runLocked(spec, queue, setResult, onConsolidation, onSuggestions, onReady, onSuspend, manualCompactRef, taskIdRef, resume, internals) {
464
486
  const prepareResume = resume
465
487
  ? {
466
488
  leafId: resume.cp.leafId,
@@ -569,6 +591,8 @@ export class Runner {
569
591
  const effectiveMaxTurns = resolveMaxTurns(spec.limits);
570
592
  const tracer = spec.tracer ?? this.deps.tracer;
571
593
  const taskId = spec.taskId ?? prepared.sessionId;
594
+ if (taskIdRef)
595
+ taskIdRef.current = taskId;
572
596
  const taskStart = Date.now();
573
597
  void Promise.resolve(this.sessions.noteTaskRun?.(prepared.sessionId, taskId)).catch(() => { });
574
598
  const recordDegraded = (info, toModel) => {
@@ -718,6 +742,7 @@ export class Runner {
718
742
  }
719
743
  const writeFamilyOf = (name) => writeFamilyByName.get(name) ?? writeFamilyOfCanonical(canonicalToolName(name));
720
744
  const toolStartAt = new Map();
745
+ const startedToolCallIds = new Set();
721
746
  emitTrace(tracer, () => ({ kind: "task.start", version: 1, taskId, model: prepared.model.id, ts: taskStart }));
722
747
  emitTrace(tracer, () => ({
723
748
  kind: "prompt.assembled",
@@ -751,6 +776,7 @@ export class Runner {
751
776
  prepared.callCapRef.deadlineMs = walltimeDeadlineMs;
752
777
  if (spec.limits?.gracefulFinalize !== false) {
753
778
  prepared.callCapRef.cushionMs = writeoutCushionMs(spec.limits.timeoutSec * 1000);
779
+ prepared.callCapRef.budgetMs = spec.limits.timeoutSec * 1000;
754
780
  }
755
781
  }
756
782
  let finalizeInjected = false;
@@ -796,6 +822,8 @@ export class Runner {
796
822
  }
797
823
  };
798
824
  const emitCommitted = (entryId, role, toolCallId) => {
825
+ if (role === "toolResult" && toolCallId !== undefined)
826
+ startedToolCallIds.delete(toolCallId);
799
827
  queue.push({ type: "message_committed", entryId, role, ...(toolCallId !== undefined ? { toolCallId } : {}), ...ident() });
800
828
  };
801
829
  const subagentName = parentToolCallId !== undefined && internals?.agentName !== undefined ? inlineUntrusted(internals.agentName.slice(0, 320), 80) : undefined;
@@ -971,6 +999,12 @@ export class Runner {
971
999
  }
972
1000
  if (m.role === "assistant" && m.errorMessage === WALLTIME_CUTOFF_MESSAGE) {
973
1001
  callCutoffs += 1;
1002
+ if (prepared.callCapRef)
1003
+ prepared.callCapRef.finalizeMode = true;
1004
+ if (!finalizeInjected) {
1005
+ finalizeInjected = true;
1006
+ nudgeIdx = nudgeSchedule.length;
1007
+ }
974
1008
  }
975
1009
  if (m.role === "assistant") {
976
1010
  const rep = m.repetition;
@@ -1030,6 +1064,7 @@ export class Runner {
1030
1064
  let toolBatch = [];
1031
1065
  const onToolStart = (event) => {
1032
1066
  toolStartAt.set(event.toolCallId, Date.now());
1067
+ startedToolCallIds.add(event.toolCallId);
1033
1068
  batchArgs?.set(event.toolCallId, event.args);
1034
1069
  stats.toolCalls += 1;
1035
1070
  if (spec.finalVerification === true && !(finalVerifyInjections === 0 ? groundingSignalPreR9 : groundingSignalPostR9) && hasVerifiableStructureSignal(event.args)) {
@@ -1421,7 +1456,7 @@ export class Runner {
1421
1456
  walltimeDeadlineMs !== undefined &&
1422
1457
  prepared.callCapRef !== undefined) {
1423
1458
  const remainingMs = walltimeDeadlineMs - nowMs;
1424
- if (remainingMs > 0 && remainingMs < estimateCycleMs(prepared.callCapRef.state) + (prepared.callCapRef.cushionMs ?? 0)) {
1459
+ if (remainingMs > 0 && remainingMs < estimateCycleMs(prepared.callCapRef.state) + (effectiveCushionMs(prepared.callCapRef) ?? 0)) {
1425
1460
  finalizeInjected = true;
1426
1461
  prepared.callCapRef.finalizeMode = true;
1427
1462
  nudgeIdx = nudgeSchedule.length;
@@ -1808,7 +1843,7 @@ export class Runner {
1808
1843
  stampWriteAnchor(attachState, family, cadenceTurns);
1809
1844
  if (details !== undefined)
1810
1845
  reduceToolEnd(attachState, details);
1811
- });
1846
+ }, (toolCallId) => startedToolCallIds.add(toolCallId));
1812
1847
  if (maxCostMicroUsd !== undefined && maxCostMicroUsd <= 0) {
1813
1848
  budgetHit = "exceeded";
1814
1849
  }
@@ -1903,7 +1938,7 @@ export class Runner {
1903
1938
  (threw !== undefined || timeout.fired || turnsExceeded || budgetHit !== undefined || abortedLive || final?.stopReason === "aborted");
1904
1939
  if (interrupted) {
1905
1940
  try {
1906
- const report = await reconcileInterruptedSession(prepared.session, prepared.toolEffects);
1941
+ const report = await reconcileInterruptedSession(prepared.session, prepared.toolEffects, undefined, startedToolCallIds);
1907
1942
  for (const orphan of report.recovered) {
1908
1943
  queue.push({ type: "tool_end", toolCallId: orphan.toolCallId, toolName: orphan.toolName, isError: true, ...ident() });
1909
1944
  emitCommitted(orphan.entryId, "toolResult", orphan.toolCallId);
@@ -1985,13 +2020,17 @@ export class Runner {
1985
2020
  }
1986
2021
  const capShrinks = prepared.callCapRef?.shrinks ?? 0;
1987
2022
  const toolClamps = prepared.callCapRef?.toolClamps ?? 0;
1988
- if (finalizeInjected || nudgesSent > 0 || capShrinks > 0 || callCutoffs > 0 || toolClamps > 0 || finalVerifyInjections > 0 || attachmentsInjected > 0 || repetitionCuts > 0 || repetitionSpared > 0) {
2023
+ const toolCuts = prepared.callCapRef?.toolCuts ?? 0;
2024
+ const pendingCutTools = prepared.callCapRef?.pendingCutTools ?? 0;
2025
+ if (finalizeInjected || nudgesSent > 0 || capShrinks > 0 || callCutoffs > 0 || toolClamps > 0 || toolCuts > 0 || pendingCutTools > 0 || finalVerifyInjections > 0 || attachmentsInjected > 0 || repetitionCuts > 0 || repetitionSpared > 0) {
1989
2026
  stats.mechanisms = {
1990
2027
  ...(finalizeInjected ? { finalizeInjected: true } : {}),
1991
2028
  ...(nudgesSent > 0 ? { nudgesSent } : {}),
1992
2029
  ...(capShrinks > 0 ? { capShrinks } : {}),
1993
2030
  ...(callCutoffs > 0 ? { callCutoffs } : {}),
1994
2031
  ...(toolClamps > 0 ? { toolClamps } : {}),
2032
+ ...(toolCuts > 0 ? { toolCuts } : {}),
2033
+ ...(pendingCutTools > 0 ? { pendingCutTools } : {}),
1995
2034
  ...(finalVerifyInjections > 0 ? { finalVerifyInjected: true } : {}),
1996
2035
  ...(finalVerifyInjections > 0 ? { finalVerifyInjections } : {}),
1997
2036
  ...(attachmentsInjected > 0 ? { attachmentsInjected } : {}),
@@ -2423,7 +2462,7 @@ export class Runner {
2423
2462
  : undefined;
2424
2463
  return this.runTaskStream(spec, { cp, outcome, onEnvRestoreFailed }, internals);
2425
2464
  }
2426
- async applyResumeDecision(prepared, resume, emit, emitCommitted, onResolvedToolSuccess) {
2465
+ async applyResumeDecision(prepared, resume, emit, emitCommitted, onResolvedToolSuccess, onExecuteStart) {
2427
2466
  const { pendingAction } = resume.cp;
2428
2467
  if (resume.outcome.gate === "dry_run_review")
2429
2468
  return;
@@ -2454,7 +2493,7 @@ export class Runner {
2454
2493
  }
2455
2494
  for (const id of pendingAction.batchToolCallIds) {
2456
2495
  if (id === pendingAction.toolCallId) {
2457
- await this.resolvePendingCall(prepared, resume, emit, emitCommitted, onResolvedToolSuccess);
2496
+ await this.resolvePendingCall(prepared, resume, emit, emitCommitted, onResolvedToolSuccess, onExecuteStart);
2458
2497
  }
2459
2498
  else if (!completed.has(id)) {
2460
2499
  const name = names.get(id) ?? "unknown";
@@ -2464,7 +2503,7 @@ export class Runner {
2464
2503
  }
2465
2504
  }
2466
2505
  }
2467
- async resolvePendingCall(prepared, resume, emit, emitCommitted, onResolvedToolSuccess) {
2506
+ async resolvePendingCall(prepared, resume, emit, emitCommitted, onResolvedToolSuccess, onExecuteStart) {
2468
2507
  const { pendingAction } = resume.cp;
2469
2508
  const { outcome } = resume;
2470
2509
  if (pendingAction.kind !== "tool_approval" || outcome.gate !== "policy_ask")
@@ -2495,26 +2534,29 @@ export class Runner {
2495
2534
  throw e;
2496
2535
  }
2497
2536
  const args = resolvedArgs;
2537
+ onExecuteStart?.(pendingAction.toolCallId);
2538
+ let res;
2498
2539
  try {
2499
- const res = await tool.execute(pendingAction.toolCallId, args, prepared.abortController.signal);
2500
- emitEnd(false);
2501
- onResolvedToolSuccess?.(canonicalToolName(pendingAction.toolName), res.details);
2502
- const eid = await prepared.session.appendMessage({
2503
- role: "toolResult",
2504
- toolCallId: pendingAction.toolCallId,
2505
- toolName: pendingAction.toolName,
2506
- content: res.content,
2507
- details: res.details,
2508
- isError: false,
2509
- timestamp: Date.now(),
2510
- });
2511
- emitCommitted(eid, "toolResult", pendingAction.toolCallId);
2540
+ res = await tool.execute(pendingAction.toolCallId, args, prepared.abortController.signal);
2512
2541
  }
2513
2542
  catch (err) {
2514
2543
  emitEnd(true);
2515
2544
  const eid = await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, `Error: ${err instanceof Error ? err.message : String(err)}`, true));
2516
2545
  emitCommitted(eid, "toolResult", pendingAction.toolCallId);
2546
+ return;
2517
2547
  }
2548
+ emitEnd(false);
2549
+ onResolvedToolSuccess?.(canonicalToolName(pendingAction.toolName), res.details);
2550
+ const eid = await prepared.session.appendMessage({
2551
+ role: "toolResult",
2552
+ toolCallId: pendingAction.toolCallId,
2553
+ toolName: pendingAction.toolName,
2554
+ content: res.content,
2555
+ details: res.details,
2556
+ isError: false,
2557
+ timestamp: Date.now(),
2558
+ });
2559
+ emitCommitted(eid, "toolResult", pendingAction.toolCallId);
2518
2560
  }
2519
2561
  seamCCompactionOptions(prepared) {
2520
2562
  if (!this.deps.summaryProvider)