@sema-agent/core 5.8.0 → 5.10.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 (68) hide show
  1. package/CHANGELOG.md +82 -0
  2. package/dist/agents/cascade.js +24 -0
  3. package/dist/agents/roster-store.d.ts +1 -0
  4. package/dist/agents/send-message-tool.js +6 -0
  5. package/dist/agents/subagent.d.ts +33 -0
  6. package/dist/agents/subagent.js +125 -33
  7. package/dist/agents/teacher.js +15 -3
  8. package/dist/agents/team.js +10 -0
  9. package/dist/agents/verify.js +7 -0
  10. package/dist/brain/anthropic.js +27 -10
  11. package/dist/brain/open-responses.d.ts +11 -0
  12. package/dist/brain/open-responses.js +736 -0
  13. package/dist/brain/openai.js +32 -5
  14. package/dist/brain/request-params.d.ts +1 -0
  15. package/dist/brain/request-params.js +16 -0
  16. package/dist/core/a2a.js +1 -1
  17. package/dist/core/fs-write-gate-policy.js +2 -2
  18. package/dist/core/lsp-diagnostics.d.ts +3 -2
  19. package/dist/core/lsp-diagnostics.js +20 -7
  20. package/dist/core/memory-recall.js +8 -3
  21. package/dist/core/memory.d.ts +5 -0
  22. package/dist/core/memory.js +6 -4
  23. package/dist/core/runner/assemble-result.d.ts +1 -0
  24. package/dist/core/runner/assemble-result.js +14 -7
  25. package/dist/core/runner/prepare-task.d.ts +9 -1
  26. package/dist/core/runner/prepare-task.js +51 -14
  27. package/dist/core/runner/runtask.d.ts +12 -0
  28. package/dist/core/runner/runtask.js +153 -42
  29. package/dist/core/runner/session-file-state-replay.d.ts +7 -0
  30. package/dist/core/runner/session-file-state-replay.js +56 -0
  31. package/dist/core/runner/session-rule-policy.d.ts +1 -0
  32. package/dist/core/runner/session-rule-policy.js +4 -3
  33. package/dist/core/runner/synthetic-tools.js +1 -1
  34. package/dist/core/runner/tool-output-projection.js +5 -4
  35. package/dist/core/session-reconcile.d.ts +7 -3
  36. package/dist/core/session-reconcile.js +3 -2
  37. package/dist/core/strategy-store.d.ts +1 -1
  38. package/dist/core/strategy-store.js +27 -4
  39. package/dist/core/task-registry-shared.d.ts +0 -1
  40. package/dist/core/tool-policy.d.ts +8 -0
  41. package/dist/core/tool-policy.js +11 -0
  42. package/dist/core/tools.js +9 -1
  43. package/dist/core/trace.d.ts +0 -2
  44. package/dist/core/types.d.ts +8 -1
  45. package/dist/engine/harness/agent-harness.d.ts +1 -0
  46. package/dist/engine/harness/agent-harness.js +3 -0
  47. package/dist/engine/harness/types.d.ts +1 -0
  48. package/dist/engine/llm/types.d.ts +2 -73
  49. package/dist/engine/loop/agent-loop.js +168 -22
  50. package/dist/engine/loop/types.d.ts +1 -0
  51. package/dist/engine/session/repo-utils.d.ts +1 -2
  52. package/dist/engine/session/repo-utils.js +0 -7
  53. package/dist/index.d.ts +3 -2
  54. package/dist/index.js +2 -1
  55. package/dist/internal/llm.d.ts +1 -1
  56. package/dist/orchestration/run-workflow-tool.js +1 -1
  57. package/dist/orchestration/workflow-governance.js +19 -0
  58. package/dist/orchestration/workflow-primitives.d.ts +1 -1
  59. package/dist/orchestration/workflow-primitives.js +4 -1
  60. package/dist/orchestration/workflow.js +15 -6
  61. package/dist/prompts/coordinator.d.ts +1 -1
  62. package/dist/prompts/coordinator.js +1 -1
  63. package/dist/stores/file/memory-store.js +3 -7
  64. package/dist/tools/fs/fs-bash.js +3 -3
  65. package/dist/tools/fs/fs-shared.d.ts +1 -0
  66. package/dist/tools/fs/fs-shared.js +4 -0
  67. package/dist/tools/web.js +20 -20
  68. package/package.json +5 -3
@@ -174,9 +174,21 @@ async function runTeacherCore(runner, studentSpec, teacher) {
174
174
  };
175
175
  };
176
176
  const tools = studentSpec.tools?.map(wrap);
177
+ const inheritedDeploymentConfig = {
178
+ ...(studentSpec.getApiKeyAndHeaders !== undefined ? { getApiKeyAndHeaders: studentSpec.getApiKeyAndHeaders } : {}),
179
+ ...(studentSpec.principal !== undefined ? { principal: studentSpec.principal } : {}),
180
+ ...(studentSpec.clientContext !== undefined ? { clientContext: studentSpec.clientContext } : {}),
181
+ ...(studentSpec.promptProfile !== undefined ? { promptProfile: studentSpec.promptProfile } : {}),
182
+ ...(studentSpec.handsReadOnly === true ? { handsReadOnly: true } : {}),
183
+ ...(studentSpec.interactiveTools === false ? { interactiveTools: false } : {}),
184
+ ...(studentSpec.excludeTools !== undefined ? { excludeTools: [...studentSpec.excludeTools] } : {}),
185
+ ...(studentSpec.deferTools !== undefined ? { deferTools: [...studentSpec.deferTools] } : {}),
186
+ ...(studentSpec.alwaysLoadTools !== undefined ? { alwaysLoadTools: [...studentSpec.alwaysLoadTools] } : {}),
187
+ ...(studentSpec.checkpointStore === null ? { checkpointStore: null } : {}),
188
+ };
177
189
  const helperBase = () => teacher.helperModel
178
- ? { model: teacher.helperModel }
179
- : { model: studentSpec.model, modelRole: studentSpec.modelRole, roles: studentSpec.roles };
190
+ ? { ...inheritedDeploymentConfig, model: teacher.helperModel }
191
+ : { ...inheritedDeploymentConfig, model: studentSpec.model, modelRole: studentSpec.modelRole, roles: studentSpec.roles };
180
192
  const teacherModelFields = () => {
181
193
  if (teacher.model) {
182
194
  return { model: teacher.model };
@@ -317,7 +329,6 @@ async function runTeacherCore(runner, studentSpec, teacher) {
317
329
  let timer;
318
330
  const promise = new Promise((res) => {
319
331
  timer = setTimeout(() => res(syntheticAborted(sid)), 10_000);
320
- timer.unref?.();
321
332
  });
322
333
  return { promise, cancel: () => { if (timer)
323
334
  clearTimeout(timer); } };
@@ -338,6 +349,7 @@ async function runTeacherCore(runner, studentSpec, teacher) {
338
349
  const askTeacher = async (trace) => {
339
350
  const r = await runner.runTask({
340
351
  objective: trace,
352
+ ...inheritedDeploymentConfig,
341
353
  ...teacherModelFields(),
342
354
  systemPrompt: teacher.prompts?.teacher ?? TEACHER_PROMPT,
343
355
  enableBlockedReport: false,
@@ -51,6 +51,16 @@ export async function runTeamDiscussion(opts) {
51
51
  let turns = 0;
52
52
  let costMicroUsd = 0;
53
53
  let failures = 0;
54
+ for (const key of ["maxTokens", "maxCostUsd"]) {
55
+ const value = opts.limits?.[key];
56
+ if (value === undefined)
57
+ continue;
58
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
59
+ const e = new Error(`TeamDiscussionOptions.limits.${key} must be a finite, non-negative number (got ${String(value)}) — the team's cumulative budget gate cannot evaluate it, and running without the gate would spend under a limit nobody chose.`);
60
+ e.code = "config.limit_invalid";
61
+ throw e;
62
+ }
63
+ }
54
64
  const budgetMaxTokens = opts.limits?.maxTokens;
55
65
  const budgetMaxCostMicroUsd = opts.limits?.maxCostUsd !== undefined ? Math.round(opts.limits.maxCostUsd * 1_000_000) : undefined;
56
66
  let budgetStop;
@@ -99,10 +99,17 @@ export async function verifyCompleted(runner, result, specBase, objective, confi
99
99
  roles: specBase.roles,
100
100
  tools: verifierTools,
101
101
  handsReadOnly: config.verifierHandsReadOnly ?? true,
102
+ interactiveTools: false,
102
103
  outputSchema: VerdictSchema,
103
104
  enableBlockedReport: false,
104
105
  limits: { ...(specBase.limits?.maxWalltimeMs !== undefined ? { maxWalltimeMs: specBase.limits.maxWalltimeMs } : {}) },
105
106
  getApiKeyAndHeaders: specBase.getApiKeyAndHeaders,
107
+ ...(specBase.principal !== undefined ? { principal: specBase.principal } : {}),
108
+ ...(specBase.excludeTools !== undefined ? { excludeTools: [...specBase.excludeTools] } : {}),
109
+ ...(specBase.deferTools !== undefined ? { deferTools: [...specBase.deferTools] } : {}),
110
+ ...(specBase.alwaysLoadTools !== undefined ? { alwaysLoadTools: [...specBase.alwaysLoadTools] } : {}),
111
+ ...(specBase.clientContext !== undefined ? { clientContext: { ...specBase.clientContext } } : {}),
112
+ ...(specBase.promptProfile !== undefined ? { promptProfile: specBase.promptProfile } : {}),
106
113
  signal: specBase.signal,
107
114
  });
108
115
  try {
@@ -516,6 +516,7 @@ export function createAnthropicBrain(config = {}) {
516
516
  const finalContent = [];
517
517
  const toolCalls = [];
518
518
  const malformed = [];
519
+ const unnamed = [];
519
520
  let anyText = false;
520
521
  let reasoningSeen = false;
521
522
  for (const [, acc] of [...blocks.entries()].sort((a, b) => a[0] - b[0])) {
@@ -537,28 +538,44 @@ export function createAnthropicBrain(config = {}) {
537
538
  anyText = true;
538
539
  }
539
540
  }
540
- else if (acc.type === "tool_use" && acc.toolName) {
541
- const tc = closeToolUseBlock(acc);
542
- if (tc) {
543
- toolCalls.push(tc);
544
- finalContent.push(tc);
541
+ else if (acc.type === "tool_use") {
542
+ if (!acc.toolName) {
543
+ unnamed.push(`id="${acc.toolId || "?"}"(${acc.toolJson.slice(0, 200)})`);
545
544
  }
546
545
  else {
547
- malformed.push(`${acc.toolName}(${acc.toolJson.slice(0, 200)})`);
546
+ const tc = closeToolUseBlock(acc);
547
+ if (tc) {
548
+ toolCalls.push(tc);
549
+ finalContent.push(tc);
550
+ }
551
+ else {
552
+ malformed.push(`${acc.toolName}(${acc.toolJson.slice(0, 200)})`);
553
+ }
548
554
  }
549
555
  }
550
556
  }
551
557
  const doneReason = mapStopReason(stopReason, toolCalls.length > 0);
552
558
  const noUsableContent = toolCalls.length === 0 && !anyText;
553
- const toolError = malformed.length > 0
554
- ? `tool call argument(s) not valid JSON (likely truncated, stop_reason="${stopReason ?? "?"}"): ${malformed.join("; ")}`
555
- : undefined;
556
- if (toolError !== undefined) {
559
+ const toolErrorParts = [];
560
+ if (malformed.length > 0) {
561
+ toolErrorParts.push(`tool call argument(s) not valid JSON (likely truncated, stop_reason="${stopReason ?? "?"}"): ${malformed.join("; ")}`);
562
+ }
563
+ if (unnamed.length > 0) {
564
+ toolErrorParts.push(`tool call(s) arrived with no tool name and cannot be executed (stop_reason="${stopReason ?? "?"}"): ${unnamed.join("; ")}`);
565
+ }
566
+ const toolError = toolErrorParts.length > 0 ? toolErrorParts.join(" | ") : undefined;
567
+ if (malformed.length > 0) {
557
568
  finalContent.push({
558
569
  type: "text",
559
570
  text: `\n[note: ${malformed.length} tool call(s) were truncated (stop_reason="${stopReason ?? "?"}") and dropped — re-issue them next turn: ${malformed.join("; ")}]`,
560
571
  });
561
572
  }
573
+ if (unnamed.length > 0) {
574
+ finalContent.push({
575
+ type: "text",
576
+ text: `\n[note: ${unnamed.length} tool call(s) arrived with no tool name and were dropped — re-issue them next turn with an explicit tool name: ${unnamed.join("; ")}]`,
577
+ });
578
+ }
562
579
  if (malformedFrames > 0) {
563
580
  finalContent.push({
564
581
  type: "text",
@@ -0,0 +1,11 @@
1
+ import type { Brain } from "../core/types.js";
2
+ import { type StreamEngineConfig } from "./stream-engine.js";
3
+ export interface OpenResponsesBrainConfig extends StreamEngineConfig {
4
+ baseUrl?: string;
5
+ apiKey?: string;
6
+ headers?: Record<string, string>;
7
+ fetchImpl?: typeof fetch;
8
+ replayReasoning?: boolean;
9
+ detectRepetition?: boolean;
10
+ }
11
+ export declare function createOpenResponsesBrain(config?: OpenResponsesBrainConfig): Brain;