@sema-agent/core
Version:
Stateless, task-oriented AI agent core
82 lines (81 loc) • 4.2 kB
JavaScript
import { Type } from "typebox";
export const TASK_OUTPUT_TOOL_NAME = "TaskOutput";
export const TASK_STOP_TOOL_NAME = "TaskStop";
export const TASK_OUTPUT_CONTRACT = { contractId: "core.task_output@1", implementationRevision: "1" };
export const TASK_STOP_CONTRACT = { contractId: "core.task_stop@1", implementationRevision: "1" };
export const TASK_OUTPUT_MISSING_ID_MESSAGE = "Error (TaskOutput): Missing required parameter: task_id";
export const TASK_STOP_MISSING_ID_MESSAGE = "Missing required parameter: task_id";
export const TASK_STOP_PARAMS = Type.Object({
task_id: Type.Optional(Type.String({ description: "The ID of the background task to stop" })),
shell_id: Type.Optional(Type.String({ description: "Deprecated: use task_id instead" })),
});
export function resolveTaskIdArg(...values) {
for (const value of values) {
if (typeof value === "string" && value.trim() !== "")
return value.trim();
}
return undefined;
}
export const REGISTRY_TASK_TOOL_CAPS = {
lanes: true,
outputFile: true,
notification: true,
blockWait: true,
nameAddressing: true,
};
export const ENV_DIRECT_TASK_TOOL_CAPS = {
lanes: false,
outputFile: false,
notification: false,
blockWait: false,
nameAddressing: false,
};
export function composeTaskOutputDescription(caps) {
const parts = [];
if (caps.outputFile) {
parts.push("[Deprecated] — for background Bash tasks, prefer Read on the output file path; for agent tasks, use the Agent tool result directly. " +
"DEPRECATED: Background tasks return their output file path in the tool result" +
(caps.notification ? ", and you receive a <task-notification> with the same path when the task completes. " : ". "));
}
parts.push("Retrieve output or status for a background task by task_id. ");
parts.push(caps.lanes
?
"Supports background Bash tasks and workflow tasks returned by Workflow. Returns only the caller's own task scope; unknown and out-of-scope ids are " +
"reported the same way. "
: "Reads a background shell started with Bash(run_in_background): returns the run status (running / exited(code) / killed / failed) plus NEW stdout/stderr since your last call. ");
if (!caps.notification) {
parts.push('When using a background command as a wait condition, call this repeatedly until status is no longer "running" — completion ' +
"is signalled by status/exitCode, not by any automatic notification; after you see a terminal status, one more " +
"poll captures any final output. ");
}
if (!caps.lanes)
parts.push("Optional `filter` is a regex keeping only matching lines.");
return parts.join("").trimEnd();
}
export function composeTaskStopDescription(caps) {
return [
"- Stops a running background task by its ID",
"- Takes a task_id parameter identifying the task to stop",
...(caps.nameAddressing ? ["- To stop a background agent spawned with a name, pass that name as task_id"] : []),
"- Returns a success or failure status",
"- Use this tool when you need to terminate a long-running task",
].join("\n");
}
export function composeTaskOutputParams(caps) {
return Type.Object({
task_id: Type.Optional(Type.String({
description: caps.lanes
? "The task_id returned by Bash(run_in_background) or Workflow."
: "The task_id returned by Bash(run_in_background).",
})),
...(caps.blockWait
? {
block: Type.Optional(Type.Boolean({
description: "Whether to wait for completion (default true — the call waits until the task finishes or `timeout`, saving re-poll turns). Pass false for an instantaneous snapshot.",
})),
timeout: Type.Optional(Type.Number({ description: "Optional timeout in milliseconds when block is true (default 30000, max 600000)." })),
}
: {}),
filter: Type.Optional(Type.String({ description: "Optional regex filter for background Bash output (sema extension)." })),
});
}