@sema-agent/core 1.286.1 → 1.288.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 (45) hide show
  1. package/dist/agents/subagent.d.ts +18 -0
  2. package/dist/agents/subagent.d.ts.map +1 -1
  3. package/dist/agents/subagent.js +98 -7
  4. package/dist/agents/subagent.js.map +1 -1
  5. package/dist/core/auto-compaction.d.ts +5 -0
  6. package/dist/core/auto-compaction.d.ts.map +1 -1
  7. package/dist/core/auto-compaction.js +19 -2
  8. package/dist/core/auto-compaction.js.map +1 -1
  9. package/dist/core/file-snapshot-store.d.ts +1 -0
  10. package/dist/core/file-snapshot-store.d.ts.map +1 -1
  11. package/dist/core/file-snapshot-store.js +8 -2
  12. package/dist/core/file-snapshot-store.js.map +1 -1
  13. package/dist/core/runner/prepare-task.d.ts.map +1 -1
  14. package/dist/core/runner/prepare-task.js +4 -1
  15. package/dist/core/runner/prepare-task.js.map +1 -1
  16. package/dist/core/runner/runtask.d.ts.map +1 -1
  17. package/dist/core/runner/runtask.js +67 -8
  18. package/dist/core/runner/runtask.js.map +1 -1
  19. package/dist/core/runner/synthetic-tools.d.ts +11 -0
  20. package/dist/core/runner/synthetic-tools.d.ts.map +1 -1
  21. package/dist/core/runner/synthetic-tools.js +44 -0
  22. package/dist/core/runner/synthetic-tools.js.map +1 -1
  23. package/dist/core/trace.d.ts +17 -0
  24. package/dist/core/trace.d.ts.map +1 -1
  25. package/dist/core/trace.js.map +1 -1
  26. package/dist/core/types.d.ts +1 -0
  27. package/dist/core/types.d.ts.map +1 -1
  28. package/dist/engine/compaction/compaction.d.ts +2 -2
  29. package/dist/engine/compaction/compaction.d.ts.map +1 -1
  30. package/dist/engine/compaction/compaction.js +13 -6
  31. package/dist/engine/compaction/compaction.js.map +1 -1
  32. package/dist/index.d.ts +2 -1
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +2 -1
  35. package/dist/index.js.map +1 -1
  36. package/dist/orchestration/workflow.d.ts.map +1 -1
  37. package/dist/orchestration/workflow.js +3 -0
  38. package/dist/orchestration/workflow.js.map +1 -1
  39. package/dist/tools/fs/index.d.ts.map +1 -1
  40. package/dist/tools/fs/index.js +14 -4
  41. package/dist/tools/fs/index.js.map +1 -1
  42. package/dist/tools/fs/search.d.ts.map +1 -1
  43. package/dist/tools/fs/search.js +3 -2
  44. package/dist/tools/fs/search.js.map +1 -1
  45. package/package.json +1 -1
@@ -220,6 +220,37 @@ export class Runner {
220
220
  if (this.deps.tiers) {
221
221
  this.deps = { ...this.deps, models: expandTiers(this.deps.models, this.deps.tiers) };
222
222
  }
223
+ if (this.deps.onError) {
224
+ const rawOnError = this.deps.onError;
225
+ const reportSinkFailure = (sinkErr, context) => {
226
+ try {
227
+ emitTrace(this.deps.tracer, () => ({
228
+ kind: "task.onerror_sink_failed",
229
+ version: 1,
230
+ sessionId: context.sessionId,
231
+ phase: context.phase,
232
+ reason: (sinkErr instanceof Error ? sinkErr.message : String(sinkErr)).slice(0, 256),
233
+ ts: Date.now(),
234
+ }));
235
+ }
236
+ catch {
237
+ }
238
+ };
239
+ this.deps = {
240
+ ...this.deps,
241
+ onError: (err, context) => {
242
+ try {
243
+ const ret = rawOnError(err, context);
244
+ if (ret !== null && ret !== undefined && typeof ret.then === "function") {
245
+ Promise.resolve(ret).then(undefined, (sinkErr) => reportSinkFailure(sinkErr, context));
246
+ }
247
+ }
248
+ catch (sinkErr) {
249
+ reportSinkFailure(sinkErr, context);
250
+ }
251
+ },
252
+ };
253
+ }
223
254
  if (!this.deps.toolResultStore) {
224
255
  this.deps = { ...this.deps, toolResultStore: new RunnerSharedToolResultStore({ maxTotalChars: 64_000_000 }) };
225
256
  }
@@ -566,7 +597,10 @@ export class Runner {
566
597
  }
567
598
  });
568
599
  const upstreamTaskNotification = internals?.onTaskNotification;
600
+ const deliveredAtTurnOpen = new Set();
569
601
  const injectTaskNotification = (notification, opts) => {
602
+ if (deliveredAtTurnOpen.has(taskNotificationDedupKey(notification)))
603
+ return;
570
604
  if (!notificationLaneLive) {
571
605
  if (notificationSessionId !== undefined)
572
606
  this.pendingSessionNotifications.pend(notificationSessionId, notification);
@@ -599,6 +633,7 @@ export class Runner {
599
633
  const pendingIdle = this.pendingSessionNotifications.drain(prepared.sessionId);
600
634
  if (pendingIdle !== undefined) {
601
635
  for (const payload of discloseDroppedPending(pendingIdle)) {
636
+ deliveredAtTurnOpen.add(taskNotificationDedupKey(payload));
602
637
  queue.push({ type: "task_notification", notification: payload });
603
638
  void prepared.harness.nextTurn(renderTaskNotificationXml(payload)).catch(() => {
604
639
  this.pendingSessionNotifications.pend(prepared.sessionId, payload);
@@ -669,12 +704,18 @@ export class Runner {
669
704
  pricing = this.deps.pricing?.[m.id] ?? modelCostToPricing(m.cost);
670
705
  cacheFamily = cacheFamilyOf(m);
671
706
  }
672
- else if (this.deps.pricing?.[info.to]) {
673
- pricing = this.deps.pricing[info.to];
707
+ else {
708
+ if (this.deps.pricing?.[info.to])
709
+ pricing = this.deps.pricing[info.to];
710
+ cacheFamily = "input-excludes-cached";
674
711
  }
675
712
  degraded = info;
676
713
  emitTrace(tracer, () => ({ kind: "task.degraded", version: 1, taskId, from: info.from, to: info.to, reason: info.reason, atTurn: info.atTurn, ts: Date.now() }));
677
- this.deps.onError?.(new Error(`degraded to a cheaper model: ${info.from} → ${info.to} (${info.reason}) at turn ${info.atTurn}`), { phase: "degraded", sessionId: prepared.sessionId });
714
+ try {
715
+ this.deps.onError?.(new Error(`degraded to a cheaper model: ${info.from} → ${info.to} (${info.reason}) at turn ${info.atTurn}`), { phase: "degraded", sessionId: prepared.sessionId });
716
+ }
717
+ catch {
718
+ }
678
719
  };
679
720
  const sliceWindowMicroUsd = spec.maxCostUsd !== undefined ? Math.round(spec.maxCostUsd * 1e6) : undefined;
680
721
  const remainingMicroUsd = prepared.resourceLedger
@@ -990,6 +1031,11 @@ export class Runner {
990
1031
  if (event.entryId !== undefined && (m.role === "user" || m.role === "assistant" || m.role === "toolResult")) {
991
1032
  emitCommitted(event.entryId, m.role, m.role === "toolResult" ? m.toolCallId : undefined);
992
1033
  }
1034
+ if (degraded === undefined && m.role === "assistant") {
1035
+ const deg = readDegradation(m);
1036
+ if (deg)
1037
+ recordDegraded({ from: deg.from, to: deg.to, reason: deg.reason, atTurn: stats.turns + 1, ...(deg.chain && { chain: deg.chain }) });
1038
+ }
993
1039
  if (m.role === "assistant" && "usage" in m && m.usage) {
994
1040
  if (m.usageMissing)
995
1041
  turnUsageMissing = true;
@@ -1120,11 +1166,6 @@ export class Runner {
1120
1166
  cadenceTurns = advanceCadenceClock(attachState, cadenceTurns, content, writeFamilyOf);
1121
1167
  lastTurnHadToolCalls = Array.isArray(content) && content.some((c) => c?.type === "toolCall");
1122
1168
  }
1123
- if (degraded === undefined && m.role === "assistant") {
1124
- const deg = readDegradation(m);
1125
- if (deg)
1126
- recordDegraded({ from: deg.from, to: deg.to, reason: deg.reason, atTurn: stats.turns + 1, ...(deg.chain && { chain: deg.chain }) });
1127
- }
1128
1169
  callStartAt = undefined;
1129
1170
  firstTokenAt = undefined;
1130
1171
  callOutputChars = 0;
@@ -1548,6 +1589,7 @@ export class Runner {
1548
1589
  ...(comp.postTriggerTokens !== undefined ? { tokensAfter: comp.postTriggerTokens } : {}),
1549
1590
  ...(comp.triggerTokens !== undefined ? { triggerTokensBefore: comp.triggerTokens } : {}),
1550
1591
  ...(comp.durationMs !== undefined ? { durationMs: comp.durationMs } : {}),
1592
+ ...(comp.phaseDurations !== undefined ? { phaseDurations: comp.phaseDurations } : {}),
1551
1593
  ...(comp.firstKeptEntryId !== undefined ? { preserved_segment: { firstKeptEntryId: comp.firstKeptEntryId } } : {}),
1552
1594
  ...(comp.attachedFiles !== undefined ? { attachedFiles: comp.attachedFiles } : {}),
1553
1595
  ...(comp.modelFallback ? { modelFallback: true } : {}),
@@ -1555,6 +1597,11 @@ export class Runner {
1555
1597
  ...(comp.clampedRatio !== undefined ? { clampedRatio: comp.clampedRatio } : {}),
1556
1598
  ...(comp.clampReason !== undefined ? { clampReason: comp.clampReason } : {}),
1557
1599
  });
1600
+ if (comp.phaseDurations !== undefined && comp.durationMs !== undefined) {
1601
+ const pd = comp.phaseDurations;
1602
+ const pdDur = comp.durationMs;
1603
+ emitTrace(tracer, () => ({ kind: "compaction.phase_timings", version: 1, taskId, ...pd, durationMs: pdDur, ts: Date.now() }));
1604
+ }
1558
1605
  prepared.cacheBreakDetector?.notifyCompaction();
1559
1606
  if (attachState !== undefined) {
1560
1607
  attachState.postCompactPending = true;
@@ -1911,6 +1958,7 @@ export class Runner {
1911
1958
  ...(comp.postTriggerTokens !== undefined ? { tokensAfter: comp.postTriggerTokens } : {}),
1912
1959
  ...(comp.triggerTokens !== undefined ? { triggerTokensBefore: comp.triggerTokens } : {}),
1913
1960
  ...(comp.durationMs !== undefined ? { durationMs: comp.durationMs } : {}),
1961
+ ...(comp.phaseDurations !== undefined ? { phaseDurations: comp.phaseDurations } : {}),
1914
1962
  ...(comp.firstKeptEntryId !== undefined ? { preserved_segment: { firstKeptEntryId: comp.firstKeptEntryId } } : {}),
1915
1963
  ...(comp.attachedFiles !== undefined ? { attachedFiles: comp.attachedFiles } : {}),
1916
1964
  ...(comp.modelFallback ? { modelFallback: true } : {}),
@@ -1918,6 +1966,11 @@ export class Runner {
1918
1966
  ...(comp.clampedRatio !== undefined ? { clampedRatio: comp.clampedRatio } : {}),
1919
1967
  ...(comp.clampReason !== undefined ? { clampReason: comp.clampReason } : {}),
1920
1968
  });
1969
+ if (comp.phaseDurations !== undefined && comp.durationMs !== undefined) {
1970
+ const pd = comp.phaseDurations;
1971
+ const pdDur = comp.durationMs;
1972
+ emitTrace(tracer, () => ({ kind: "compaction.phase_timings", version: 1, taskId, ...pd, durationMs: pdDur, ts: Date.now() }));
1973
+ }
1921
1974
  prepared.cacheBreakDetector?.notifyCompaction();
1922
1975
  if (attachState !== undefined) {
1923
1976
  attachState.postCompactPending = true;
@@ -2137,6 +2190,7 @@ export class Runner {
2137
2190
  ...(comp.postTriggerTokens !== undefined ? { tokensAfter: comp.postTriggerTokens } : {}),
2138
2191
  ...(comp.triggerTokens !== undefined ? { triggerTokensBefore: comp.triggerTokens } : {}),
2139
2192
  ...(comp.durationMs !== undefined ? { durationMs: comp.durationMs } : {}),
2193
+ ...(comp.phaseDurations !== undefined ? { phaseDurations: comp.phaseDurations } : {}),
2140
2194
  ...(comp.firstKeptEntryId !== undefined ? { preserved_segment: { firstKeptEntryId: comp.firstKeptEntryId } } : {}),
2141
2195
  ...(comp.attachedFiles !== undefined ? { attachedFiles: comp.attachedFiles } : {}),
2142
2196
  ...(comp.modelFallback ? { modelFallback: true } : {}),
@@ -2144,6 +2198,11 @@ export class Runner {
2144
2198
  ...(comp.clampedRatio !== undefined ? { clampedRatio: comp.clampedRatio } : {}),
2145
2199
  ...(comp.clampReason !== undefined ? { clampReason: comp.clampReason } : {}),
2146
2200
  });
2201
+ if (comp.phaseDurations !== undefined && comp.durationMs !== undefined) {
2202
+ const pd = comp.phaseDurations;
2203
+ const pdDur = comp.durationMs;
2204
+ emitTrace(tracer, () => ({ kind: "compaction.phase_timings", version: 1, taskId, ...pd, durationMs: pdDur, ts: Date.now() }));
2205
+ }
2147
2206
  prepared.cacheBreakDetector?.notifyCompaction();
2148
2207
  }
2149
2208
  if (prepared.nestedStats.tasks > 0) {