@sema-agent/core 1.443.0 → 1.444.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,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { readFileSync, realpathSync, createWriteStream } from "node:fs";
3
3
  import { pathToFileURL } from "node:url";
4
- import { Runner, NodeExecutionEnv, createOpenAIBrain, createAnthropicBrain, CODE_SYSTEM_PROMPT, assembleCodeTools, } from "../index.js";
4
+ import { Runner, NodeExecutionEnv, createOpenAIBrain, createAnthropicBrain, CODE_SYSTEM_PROMPT, assembleCodeTools, makeWebFetchSummarizer, } from "../index.js";
5
5
  import { positiveIntFromEnv } from "./tb-env.js";
6
6
  import { inferMaxTokensField } from "../brain/openai.js";
7
7
  function usage(code = 2) {
@@ -242,36 +242,6 @@ function intFromEnv(name, fallback) {
242
242
  const n = Number.parseInt(raw, 10);
243
243
  return Number.isFinite(n) && n > 0 ? n : fallback;
244
244
  }
245
- const WEBFETCH_SUMMARY_MAX_CONTENT = 100_000;
246
- function makeWebFetchSummarizer(brain, model) {
247
- return async (content, prompt, signal) => {
248
- const truncated = content.length > WEBFETCH_SUMMARY_MAX_CONTENT
249
- ? content.slice(0, WEBFETCH_SUMMARY_MAX_CONTENT) + "\n\n[Content truncated due to length...]"
250
- : content;
251
- const userPrompt = `\nWeb page content:\n---\n${truncated}\n---\n\n${prompt}\n\n` +
252
- `Provide a concise response based only on the content above. In your response:\n` +
253
- ` - Enforce a strict 125-character maximum for quotes from any source document. Open Source Software is ok as long as we respect the license.\n` +
254
- ` - Use quotation marks for exact language from articles; any language outside of the quotation should never be word-for-word the same.\n` +
255
- ` - You are not a lawyer and never comment on the legality of your own prompts and responses.\n` +
256
- ` - Never produce or reproduce exact song lyrics.\n`;
257
- const context = { messages: [{ role: "user", content: userPrompt, timestamp: Date.now() }] };
258
- const msg = brain.complete
259
- ? await brain.complete(model, context, { signal })
260
- : await (await Promise.resolve(brain.stream(model, context, { signal }))).result();
261
- const am = msg;
262
- if (am?.stopReason === "error" || am?.stopReason === "aborted") {
263
- throw new Error(am.errorMessage ?? `summarizer stopped with ${am.stopReason}`);
264
- }
265
- const text = (am?.content ?? [])
266
- .filter((b) => b?.type === "text" && typeof b.text === "string")
267
- .map((b) => b.text)
268
- .join("\n")
269
- .trim();
270
- if (!text)
271
- throw new Error("summarizer returned no text");
272
- return text;
273
- };
274
- }
275
245
  async function main() {
276
246
  process.title = "sema-tb-agent";
277
247
  const parsed = parseArgs(process.argv.slice(2));
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@ export { SKILL_TOOL_NAME } from "./core/runner/synthetic-tools.js";
6
6
  export { REPORT_FINDINGS_TOOL_NAME, type ReportedFinding } from "./core/runner/synthetic-tools.js";
7
7
  export { formatToolError, formatZodValidationError, formatValidationPath, truncateError, errorClassOf } from "./core/tool-errors.js";
8
8
  export type { WorkerErrorClass } from "./core/tool-errors.js";
9
- export { createWebFetchTool, webFetchToolSpec, htmlToText, type WebFetchConfig, createWebSearchTool, type WebSearchConfig } from "./tools/web.js";
9
+ export { createWebFetchTool, webFetchToolSpec, htmlToText, type WebFetchConfig, createWebSearchTool, type WebSearchConfig, makeWebFetchSummarizer, WEBFETCH_SUMMARY_MAX_CONTENT, WEBFETCH_SUMMARY_GUIDELINES, } from "./tools/web.js";
10
10
  export { createTodoWriteTool } from "./tools/todo.js";
11
11
  export { createTaskListTools, createMemoryTaskListStore, assertJsonMetadata, type TaskListItem, type TaskListStore } from "./tools/task-list.js";
12
12
  export { assembleCodeTools, type CodeToolsConfig, CODE_ROLE, assembleFullBodyTools, type FullBodyToolsConfig, FULL_BODY_ROLE } from "./scenarios/full-body.js";
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ export { defineTool, toSkill } from "./core/tools.js";
4
4
  export { SKILL_TOOL_NAME } from "./core/runner/synthetic-tools.js";
5
5
  export { REPORT_FINDINGS_TOOL_NAME } from "./core/runner/synthetic-tools.js";
6
6
  export { formatToolError, formatZodValidationError, formatValidationPath, truncateError, errorClassOf } from "./core/tool-errors.js";
7
- export { createWebFetchTool, webFetchToolSpec, htmlToText, createWebSearchTool } from "./tools/web.js";
7
+ export { createWebFetchTool, webFetchToolSpec, htmlToText, createWebSearchTool, makeWebFetchSummarizer, WEBFETCH_SUMMARY_MAX_CONTENT, WEBFETCH_SUMMARY_GUIDELINES, } from "./tools/web.js";
8
8
  export { createTodoWriteTool } from "./tools/todo.js";
9
9
  export { createTaskListTools, createMemoryTaskListStore, assertJsonMetadata } from "./tools/task-list.js";
10
10
  export { assembleCodeTools, CODE_ROLE, assembleFullBodyTools, FULL_BODY_ROLE } from "./scenarios/full-body.js";
@@ -1,5 +1,6 @@
1
1
  import type { AgentTool } from "../internal/harness.js";
2
- import type { ToolSpec } from "../core/types.js";
2
+ import type { Brain, ToolSpec } from "../core/types.js";
3
+ import type { Model } from "../internal/llm.js";
3
4
  export interface WebFetchConfig {
4
5
  allowHosts?: string[];
5
6
  fetchImpl?: typeof fetch;
@@ -11,6 +12,9 @@ export interface WebFetchConfig {
11
12
  export declare function htmlToText(html: string): string;
12
13
  export declare function webFetchToolSpec(config?: WebFetchConfig): ToolSpec;
13
14
  export declare function createWebFetchTool(config?: WebFetchConfig): AgentTool;
15
+ export declare const WEBFETCH_SUMMARY_MAX_CONTENT = 100000;
16
+ export declare const WEBFETCH_SUMMARY_GUIDELINES: string;
17
+ export declare function makeWebFetchSummarizer(brain: Brain, model: Model): (content: string, prompt: string, signal?: AbortSignal) => Promise<string>;
14
18
  export interface WebSearchConfig {
15
19
  search: (query: string, signal?: AbortSignal, opts?: {
16
20
  allowedDomains?: string[];
package/dist/tools/web.js CHANGED
@@ -541,6 +541,36 @@ export function webFetchToolSpec(config = {}) {
541
541
  export function createWebFetchTool(config = {}) {
542
542
  return defineTool(webFetchToolSpec(config));
543
543
  }
544
+ export const WEBFETCH_SUMMARY_MAX_CONTENT = 100_000;
545
+ export const WEBFETCH_SUMMARY_GUIDELINES = `Provide a concise response based only on the content above. In your response:\n` +
546
+ ` - Enforce a strict 125-character maximum for quotes from any source document. Open Source Software is ok as long as we respect the license.\n` +
547
+ ` - Use quotation marks for exact language from articles; any language outside of the quotation should never be word-for-word the same.\n` +
548
+ ` - You are not a lawyer and never comment on the legality of your own prompts and responses.\n` +
549
+ ` - Never produce or reproduce exact song lyrics.\n`;
550
+ export function makeWebFetchSummarizer(brain, model) {
551
+ return async (content, prompt, signal) => {
552
+ const truncated = content.length > WEBFETCH_SUMMARY_MAX_CONTENT
553
+ ? content.slice(0, WEBFETCH_SUMMARY_MAX_CONTENT) + "\n\n[Content truncated due to length...]"
554
+ : content;
555
+ const userPrompt = `\nWeb page content:\n---\n${truncated}\n---\n\n${prompt}\n\n` + WEBFETCH_SUMMARY_GUIDELINES;
556
+ const context = { messages: [{ role: "user", content: userPrompt, timestamp: Date.now() }] };
557
+ const msg = brain.complete
558
+ ? await brain.complete(model, context, { signal })
559
+ : await (await Promise.resolve(brain.stream(model, context, { signal }))).result();
560
+ const am = msg;
561
+ if (am?.stopReason === "error" || am?.stopReason === "aborted") {
562
+ throw new Error(am.errorMessage ?? `summarizer stopped with ${am.stopReason}`);
563
+ }
564
+ const text = (am?.content ?? [])
565
+ .filter((b) => b?.type === "text" && typeof b.text === "string")
566
+ .map((b) => b.text)
567
+ .join("\n")
568
+ .trim();
569
+ if (!text)
570
+ throw new Error("summarizer returned no text");
571
+ return text;
572
+ };
573
+ }
544
574
  function hostMatchesDomain(host, domain) {
545
575
  const d = domain.toLowerCase().replace(/^\*\./, "").replace(/^\.+|\.+$/g, "");
546
576
  if (!d)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/core",
3
- "version": "1.443.0",
3
+ "version": "1.444.0",
4
4
  "description": "Stateless, task-oriented AI agent core",
5
5
  "type": "module",
6
6
  "license": "BUSL-1.1",