Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

agentool

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

agentool - npm Package Compare versions

Comparing version
1.5.0
to
1.5.1
+418
dist/chunk-6SEZNYRX.js
import {
extractErrorMessage
} from "./chunk-X6ZY2KFU.js";
// src/agent/index.ts
import { generateText, stepCountIs, tool } from "ai";
import { randomUUID } from "crypto";
import { setTimeout as sleep } from "timers/promises";
// src/agent/constants.ts
var DEFAULT_AGENT_NAME = "default";
var DEFAULT_MAX_CONCURRENT = 4;
var DEFAULT_RUN_TIMEOUT_MS = 3e5;
var DEFAULT_WAIT_TIMEOUT_MS = 3e4;
var DEFAULT_POLL_INTERVAL_MS = 500;
var DEFAULT_RESULT_CHARS = 3e4;
var DEFAULT_MAX_TURNS = 20;
var terminalStatuses = /* @__PURE__ */ new Set([
"completed",
"failed",
"stopped",
"timed_out"
]);
var fallbackAgent = {
description: "General purpose subagent",
systemPrompt: "You are a focused subagent. Complete the delegated task and report concise findings back to the orchestrator."
};
// src/agent/format.ts
function isTerminal(task) {
return terminalStatuses.has(task.status);
}
function truncateResult(value, maxChars) {
if (value.length <= maxChars) return value;
const omitted = value.length - maxChars;
return `${value.slice(0, maxChars)}
... [agent result truncated - ${omitted} chars removed]`;
}
function formatUsage(usage) {
if (!usage) return "";
const parts = [
usage.inputTokens === void 0 ? void 0 : `input=${usage.inputTokens}`,
usage.outputTokens === void 0 ? void 0 : `output=${usage.outputTokens}`,
usage.totalTokens === void 0 ? void 0 : `total=${usage.totalTokens}`
].filter((part) => part !== void 0);
return parts.length > 0 ? `
Usage: ${parts.join(", ")}` : "";
}
function formatTaskSummary(task) {
const elapsedMs = (task.endTime ?? Date.now()) - task.startTime;
const label = task.description ? ` (${task.description})` : "";
const error = task.error ? `
Error: ${task.error}` : "";
return `Task ${task.id}${label}
Agent: ${task.agentName}
Status: ${task.status}
Elapsed: ${elapsedMs}ms${formatUsage(task.usage)}${error}`;
}
function formatTaskResult(task, maxResultChars) {
const summary = formatTaskSummary(task);
if (task.status === "completed") {
return `${summary}
Result:
${truncateResult(task.result ?? "", maxResultChars)}`;
}
if (task.status === "running") {
return `${summary}
Result is not ready yet. Use wait or status later.`;
}
return summary;
}
function formatWaitResult(tasks, mode, timedOut, maxResultChars) {
const completed = tasks.filter(isTerminal);
const running = tasks.filter((task) => task.status === "running");
const header = timedOut ? `Wait timed out. ${completed.length}/${tasks.length} selected task(s) finished.` : `Wait complete (${mode}). ${completed.length}/${tasks.length} selected task(s) finished.`;
const sections = completed.map((task) => formatTaskResult(task, maxResultChars));
const runningLines = running.map(
(task) => `Task ${task.id}: running${task.description ? ` (${task.description})` : ""}`
);
return [header, ...sections, ...runningLines].join("\n\n");
}
// src/agent/prompt.ts
function getPrompt(config = {}) {
const names = Object.keys(config.agents ?? {});
const registryLine = names.length > 0 ? `Configured agents: ${names.join(", ")}.` : "No named agents are configured; the built-in default agent is used.";
return `Spawn and manage parallel subagents.
Use this tool when work can be split into focused independent investigations or checks.
${registryLine}
Actions:
- start: launch a subagent in the background and return a task id immediately.
- wait: wait internally for any or all selected tasks to finish.
- status: inspect one task.
- result: read one completed task result.
- list: show known tasks.
- stop: abort a running task.
Guidelines:
- Start multiple independent subagents before waiting when parallel work helps.
- Use wait instead of repeatedly polling status.
- Subagents do not receive this agent tool recursively.
- If a result is incomplete, start a narrower follow-up subagent or investigate directly.
- Stop tasks that are no longer useful.`;
}
// src/agent/schema.ts
import { jsonSchema } from "ai";
import { z } from "zod";
var validationSchema = z.discriminatedUnion("action", [
z.object({
action: z.literal("start"),
agent: z.string().optional().describe("Configured agent name to run"),
prompt: z.string().describe("User prompt for the subagent"),
description: z.string().optional().describe("Short task label"),
timeoutMs: z.number().int().positive().optional().describe("Run timeout in milliseconds")
}),
z.object({
action: z.literal("wait"),
taskIds: z.array(z.string()).optional().describe("Task ids to wait for. Defaults to all running tasks."),
mode: z.enum(["all", "any"]).optional().default("all").describe("Wait for all selected tasks or the first selected task"),
timeoutMs: z.number().int().nonnegative().optional().describe("Wait timeout in milliseconds"),
pollIntervalMs: z.number().int().positive().optional().describe("Internal polling interval in milliseconds")
}),
z.object({
action: z.literal("status"),
taskId: z.string().describe("Task id to inspect")
}),
z.object({
action: z.literal("result"),
taskId: z.string().describe("Task id to read")
}),
z.object({
action: z.literal("list")
}),
z.object({
action: z.literal("stop"),
taskId: z.string().describe("Task id to stop")
})
]);
var inputSchema = jsonSchema(
{
type: "object",
properties: {
action: {
type: "string",
enum: ["start", "wait", "status", "result", "list", "stop"],
description: "Agent task action to perform"
},
agent: {
type: "string",
description: "Configured agent name to run"
},
prompt: {
type: "string",
description: "User prompt for the subagent. Required when action is start."
},
description: {
type: "string",
description: "Short task label"
},
timeoutMs: {
type: "integer",
minimum: 0,
description: "Run or wait timeout in milliseconds"
},
taskIds: {
type: "array",
items: { type: "string" },
description: "Task ids to wait for. Defaults to all running tasks."
},
mode: {
type: "string",
enum: ["all", "any"],
default: "all",
description: "Wait for all selected tasks or the first selected task"
},
pollIntervalMs: {
type: "integer",
exclusiveMinimum: 0,
description: "Internal polling interval in milliseconds"
},
taskId: {
type: "string",
description: "Task id to inspect, read, or stop. Required when action is status, result, or stop."
}
},
required: ["action"],
additionalProperties: false,
$schema: "http://json-schema.org/draft-07/schema#"
},
{
validate: async (value) => {
const result = await validationSchema.safeParseAsync(value);
return result.success ? { success: true, value: result.data } : { success: false, error: result.error };
}
}
);
// src/agent/tasks.ts
function activeTaskCount(tasks) {
let count = 0;
for (const task of tasks.values()) {
if (task.status === "running") count++;
}
return count;
}
function selectAgent(config, requestedName) {
const registry = config.agents ?? {};
const registryNames = Object.keys(registry);
const name = requestedName ?? config.defaultAgent ?? registryNames[0] ?? DEFAULT_AGENT_NAME;
const definition = registry[name] ?? (name === DEFAULT_AGENT_NAME && registryNames.length === 0 ? fallbackAgent : void 0);
if (!definition) {
const available = registryNames.length > 0 ? registryNames.join(", ") : DEFAULT_AGENT_NAME;
return `Unknown agent "${name}". Available agents: ${available}.`;
}
return { name, definition };
}
function getWaitTargets(tasks, taskIds) {
if (taskIds && taskIds.length > 0) {
const selected = [];
const missing = [];
for (const taskId of taskIds) {
const task = tasks.get(taskId);
if (task) selected.push(task);
else missing.push(taskId);
}
if (missing.length > 0) {
return `Unknown task id(s): ${missing.join(", ")}.`;
}
return selected;
}
return Array.from(tasks.values()).filter((task) => task.status === "running");
}
function stopTask(task, status, error) {
if (task.status !== "running") return;
task.status = status;
task.error = error;
task.endTime = Date.now();
if (task.timeoutId) {
clearTimeout(task.timeoutId);
task.timeoutId = void 0;
}
task.abortController.abort();
}
// src/agent/tools.ts
var AGENT_TOOL_NAME = "agent";
var agentTools = /* @__PURE__ */ new WeakSet();
function markAgentTool(agentTool) {
agentTools.add(agentTool);
return agentTool;
}
function isMarkedAgentTool(value) {
return typeof value === "object" && value !== null && agentTools.has(value);
}
function removeAgentTools(tools) {
if (!tools) return tools;
const toolEntries = Object.entries(tools);
const entries = toolEntries.filter(
([name, value]) => name !== AGENT_TOOL_NAME && !isMarkedAgentTool(value)
);
if (entries.length === toolEntries.length) return tools;
if (entries.length === 0) return void 0;
return Object.fromEntries(entries);
}
// src/agent/index.ts
function createAgent(config = {}) {
const tasks = /* @__PURE__ */ new Map();
const maxConcurrent = config.maxConcurrent ?? DEFAULT_MAX_CONCURRENT;
const defaultRunTimeoutMs = config.defaultTimeoutMs ?? DEFAULT_RUN_TIMEOUT_MS;
const defaultWaitTimeoutMs = config.defaultWaitTimeoutMs ?? DEFAULT_WAIT_TIMEOUT_MS;
const defaultPollIntervalMs = config.defaultPollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
const maxResultChars = config.maxResultChars ?? DEFAULT_RESULT_CHARS;
function startTask(input) {
if (activeTaskCount(tasks) >= maxConcurrent) {
return `Error [agent]: Max concurrent subagents reached (${maxConcurrent}). Use wait, result, or stop before starting more.`;
}
const selected = selectAgent(config, input.agent);
if (typeof selected === "string") {
return `Error [agent]: ${selected}`;
}
const model = selected.definition.model ?? config.model;
if (!model) {
return "Error [agent]: No model configured. Provide createAgent({ model }) or an agent-specific model.";
}
const taskId = `agent_${randomUUID()}`;
const abortController = new AbortController();
const timeoutMs = input.timeoutMs ?? defaultRunTimeoutMs;
const task = {
id: taskId,
agentName: selected.name,
description: input.description,
prompt: input.prompt,
status: "running",
startTime: Date.now(),
abortController,
promise: Promise.resolve()
};
tasks.set(taskId, task);
task.timeoutId = setTimeout(() => {
stopTask(
task,
"timed_out",
`Subagent timed out after ${timeoutMs}ms.`
);
}, timeoutMs);
task.promise = (async () => {
try {
const maxTurns = selected.definition.maxTurns ?? config.maxTurns ?? DEFAULT_MAX_TURNS;
const stopWhen = selected.definition.stopWhen ?? config.stopWhen ?? stepCountIs(maxTurns);
const result = await generateText({
...config.settings ?? {},
...selected.definition.settings ?? {},
model,
tools: removeAgentTools(selected.definition.tools ?? config.tools),
system: selected.definition.systemPrompt,
prompt: input.prompt,
stopWhen,
abortSignal: abortController.signal
});
if (task.status === "running") {
task.status = "completed";
task.result = result.text;
task.usage = result.usage;
task.endTime = Date.now();
}
} catch (error) {
if (task.status === "running") {
task.status = "failed";
task.error = extractErrorMessage(error);
task.endTime = Date.now();
}
} finally {
if (task.timeoutId) {
clearTimeout(task.timeoutId);
task.timeoutId = void 0;
}
}
})();
return `Started subagent task ${taskId}.
Agent: ${selected.name}
Status: running
Use wait with taskIds ["${taskId}"] or wait for all running tasks.`;
}
async function waitForTasks(input, abortSignal) {
const targets = getWaitTargets(tasks, input.taskIds);
if (typeof targets === "string") return `Error [agent]: ${targets}`;
if (targets.length === 0) {
return "No running or selected subagent tasks to wait for.";
}
const mode = input.mode;
const timeoutMs = input.timeoutMs ?? defaultWaitTimeoutMs;
const pollIntervalMs = input.pollIntervalMs ?? defaultPollIntervalMs;
const deadline = Date.now() + timeoutMs;
while (true) {
const completed = targets.filter(isTerminal);
const done = mode === "any" ? completed.length > 0 : completed.length === targets.length;
if (done) {
return formatWaitResult(targets, mode, false, maxResultChars);
}
const remainingMs = deadline - Date.now();
if (remainingMs <= 0) {
return formatWaitResult(targets, mode, true, maxResultChars);
}
await sleep(Math.min(pollIntervalMs, remainingMs), void 0, {
signal: abortSignal
});
}
}
return markAgentTool(tool({
description: config.description ?? getPrompt(config),
inputSchema,
execute: async (input, options) => {
try {
switch (input.action) {
case "start":
return startTask(input);
case "wait":
return await waitForTasks(input, options.abortSignal);
case "status": {
const task = tasks.get(input.taskId);
return task ? formatTaskSummary(task) : `Error [agent]: Unknown task id "${input.taskId}".`;
}
case "result": {
const task = tasks.get(input.taskId);
return task ? formatTaskResult(task, maxResultChars) : `Error [agent]: Unknown task id "${input.taskId}".`;
}
case "list": {
if (tasks.size === 0) return "No subagent tasks have been started.";
return Array.from(tasks.values()).sort((a, b) => a.startTime - b.startTime).map(formatTaskSummary).join("\n\n");
}
case "stop": {
const task = tasks.get(input.taskId);
if (!task) return `Error [agent]: Unknown task id "${input.taskId}".`;
if (task.status !== "running") {
return `Task ${task.id} is already ${task.status}.`;
}
stopTask(task, "stopped", "Subagent stopped by orchestrator.");
return `Stopped subagent task ${task.id}.`;
}
}
} catch (error) {
return `Error [agent]: ${extractErrorMessage(error)}`;
}
}
}));
}
var agent = createAgent();
export {
getPrompt,
createAgent,
agent
};
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
var _chunkKONXT2SFcjs = require('./chunk-KONXT2SF.cjs');
// src/agent/index.ts
var _ai = require('ai');
var _crypto = require('crypto');
var _promises = require('timers/promises');
// src/agent/constants.ts
var DEFAULT_AGENT_NAME = "default";
var DEFAULT_MAX_CONCURRENT = 4;
var DEFAULT_RUN_TIMEOUT_MS = 3e5;
var DEFAULT_WAIT_TIMEOUT_MS = 3e4;
var DEFAULT_POLL_INTERVAL_MS = 500;
var DEFAULT_RESULT_CHARS = 3e4;
var DEFAULT_MAX_TURNS = 20;
var terminalStatuses = /* @__PURE__ */ new Set([
"completed",
"failed",
"stopped",
"timed_out"
]);
var fallbackAgent = {
description: "General purpose subagent",
systemPrompt: "You are a focused subagent. Complete the delegated task and report concise findings back to the orchestrator."
};
// src/agent/format.ts
function isTerminal(task) {
return terminalStatuses.has(task.status);
}
function truncateResult(value, maxChars) {
if (value.length <= maxChars) return value;
const omitted = value.length - maxChars;
return `${value.slice(0, maxChars)}
... [agent result truncated - ${omitted} chars removed]`;
}
function formatUsage(usage) {
if (!usage) return "";
const parts = [
usage.inputTokens === void 0 ? void 0 : `input=${usage.inputTokens}`,
usage.outputTokens === void 0 ? void 0 : `output=${usage.outputTokens}`,
usage.totalTokens === void 0 ? void 0 : `total=${usage.totalTokens}`
].filter((part) => part !== void 0);
return parts.length > 0 ? `
Usage: ${parts.join(", ")}` : "";
}
function formatTaskSummary(task) {
const elapsedMs = (_nullishCoalesce(task.endTime, () => ( Date.now()))) - task.startTime;
const label = task.description ? ` (${task.description})` : "";
const error = task.error ? `
Error: ${task.error}` : "";
return `Task ${task.id}${label}
Agent: ${task.agentName}
Status: ${task.status}
Elapsed: ${elapsedMs}ms${formatUsage(task.usage)}${error}`;
}
function formatTaskResult(task, maxResultChars) {
const summary = formatTaskSummary(task);
if (task.status === "completed") {
return `${summary}
Result:
${truncateResult(_nullishCoalesce(task.result, () => ( "")), maxResultChars)}`;
}
if (task.status === "running") {
return `${summary}
Result is not ready yet. Use wait or status later.`;
}
return summary;
}
function formatWaitResult(tasks, mode, timedOut, maxResultChars) {
const completed = tasks.filter(isTerminal);
const running = tasks.filter((task) => task.status === "running");
const header = timedOut ? `Wait timed out. ${completed.length}/${tasks.length} selected task(s) finished.` : `Wait complete (${mode}). ${completed.length}/${tasks.length} selected task(s) finished.`;
const sections = completed.map((task) => formatTaskResult(task, maxResultChars));
const runningLines = running.map(
(task) => `Task ${task.id}: running${task.description ? ` (${task.description})` : ""}`
);
return [header, ...sections, ...runningLines].join("\n\n");
}
// src/agent/prompt.ts
function getPrompt(config = {}) {
const names = Object.keys(_nullishCoalesce(config.agents, () => ( {})));
const registryLine = names.length > 0 ? `Configured agents: ${names.join(", ")}.` : "No named agents are configured; the built-in default agent is used.";
return `Spawn and manage parallel subagents.
Use this tool when work can be split into focused independent investigations or checks.
${registryLine}
Actions:
- start: launch a subagent in the background and return a task id immediately.
- wait: wait internally for any or all selected tasks to finish.
- status: inspect one task.
- result: read one completed task result.
- list: show known tasks.
- stop: abort a running task.
Guidelines:
- Start multiple independent subagents before waiting when parallel work helps.
- Use wait instead of repeatedly polling status.
- Subagents do not receive this agent tool recursively.
- If a result is incomplete, start a narrower follow-up subagent or investigate directly.
- Stop tasks that are no longer useful.`;
}
// src/agent/schema.ts
var _zod = require('zod');
var validationSchema = _zod.z.discriminatedUnion("action", [
_zod.z.object({
action: _zod.z.literal("start"),
agent: _zod.z.string().optional().describe("Configured agent name to run"),
prompt: _zod.z.string().describe("User prompt for the subagent"),
description: _zod.z.string().optional().describe("Short task label"),
timeoutMs: _zod.z.number().int().positive().optional().describe("Run timeout in milliseconds")
}),
_zod.z.object({
action: _zod.z.literal("wait"),
taskIds: _zod.z.array(_zod.z.string()).optional().describe("Task ids to wait for. Defaults to all running tasks."),
mode: _zod.z.enum(["all", "any"]).optional().default("all").describe("Wait for all selected tasks or the first selected task"),
timeoutMs: _zod.z.number().int().nonnegative().optional().describe("Wait timeout in milliseconds"),
pollIntervalMs: _zod.z.number().int().positive().optional().describe("Internal polling interval in milliseconds")
}),
_zod.z.object({
action: _zod.z.literal("status"),
taskId: _zod.z.string().describe("Task id to inspect")
}),
_zod.z.object({
action: _zod.z.literal("result"),
taskId: _zod.z.string().describe("Task id to read")
}),
_zod.z.object({
action: _zod.z.literal("list")
}),
_zod.z.object({
action: _zod.z.literal("stop"),
taskId: _zod.z.string().describe("Task id to stop")
})
]);
var inputSchema = _ai.jsonSchema.call(void 0,
{
type: "object",
properties: {
action: {
type: "string",
enum: ["start", "wait", "status", "result", "list", "stop"],
description: "Agent task action to perform"
},
agent: {
type: "string",
description: "Configured agent name to run"
},
prompt: {
type: "string",
description: "User prompt for the subagent. Required when action is start."
},
description: {
type: "string",
description: "Short task label"
},
timeoutMs: {
type: "integer",
minimum: 0,
description: "Run or wait timeout in milliseconds"
},
taskIds: {
type: "array",
items: { type: "string" },
description: "Task ids to wait for. Defaults to all running tasks."
},
mode: {
type: "string",
enum: ["all", "any"],
default: "all",
description: "Wait for all selected tasks or the first selected task"
},
pollIntervalMs: {
type: "integer",
exclusiveMinimum: 0,
description: "Internal polling interval in milliseconds"
},
taskId: {
type: "string",
description: "Task id to inspect, read, or stop. Required when action is status, result, or stop."
}
},
required: ["action"],
additionalProperties: false,
$schema: "http://json-schema.org/draft-07/schema#"
},
{
validate: async (value) => {
const result = await validationSchema.safeParseAsync(value);
return result.success ? { success: true, value: result.data } : { success: false, error: result.error };
}
}
);
// src/agent/tasks.ts
function activeTaskCount(tasks) {
let count = 0;
for (const task of tasks.values()) {
if (task.status === "running") count++;
}
return count;
}
function selectAgent(config, requestedName) {
const registry = _nullishCoalesce(config.agents, () => ( {}));
const registryNames = Object.keys(registry);
const name = _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(requestedName, () => ( config.defaultAgent)), () => ( registryNames[0])), () => ( DEFAULT_AGENT_NAME));
const definition = _nullishCoalesce(registry[name], () => ( (name === DEFAULT_AGENT_NAME && registryNames.length === 0 ? fallbackAgent : void 0)));
if (!definition) {
const available = registryNames.length > 0 ? registryNames.join(", ") : DEFAULT_AGENT_NAME;
return `Unknown agent "${name}". Available agents: ${available}.`;
}
return { name, definition };
}
function getWaitTargets(tasks, taskIds) {
if (taskIds && taskIds.length > 0) {
const selected = [];
const missing = [];
for (const taskId of taskIds) {
const task = tasks.get(taskId);
if (task) selected.push(task);
else missing.push(taskId);
}
if (missing.length > 0) {
return `Unknown task id(s): ${missing.join(", ")}.`;
}
return selected;
}
return Array.from(tasks.values()).filter((task) => task.status === "running");
}
function stopTask(task, status, error) {
if (task.status !== "running") return;
task.status = status;
task.error = error;
task.endTime = Date.now();
if (task.timeoutId) {
clearTimeout(task.timeoutId);
task.timeoutId = void 0;
}
task.abortController.abort();
}
// src/agent/tools.ts
var AGENT_TOOL_NAME = "agent";
var agentTools = /* @__PURE__ */ new WeakSet();
function markAgentTool(agentTool) {
agentTools.add(agentTool);
return agentTool;
}
function isMarkedAgentTool(value) {
return typeof value === "object" && value !== null && agentTools.has(value);
}
function removeAgentTools(tools) {
if (!tools) return tools;
const toolEntries = Object.entries(tools);
const entries = toolEntries.filter(
([name, value]) => name !== AGENT_TOOL_NAME && !isMarkedAgentTool(value)
);
if (entries.length === toolEntries.length) return tools;
if (entries.length === 0) return void 0;
return Object.fromEntries(entries);
}
// src/agent/index.ts
function createAgent(config = {}) {
const tasks = /* @__PURE__ */ new Map();
const maxConcurrent = _nullishCoalesce(config.maxConcurrent, () => ( DEFAULT_MAX_CONCURRENT));
const defaultRunTimeoutMs = _nullishCoalesce(config.defaultTimeoutMs, () => ( DEFAULT_RUN_TIMEOUT_MS));
const defaultWaitTimeoutMs = _nullishCoalesce(config.defaultWaitTimeoutMs, () => ( DEFAULT_WAIT_TIMEOUT_MS));
const defaultPollIntervalMs = _nullishCoalesce(config.defaultPollIntervalMs, () => ( DEFAULT_POLL_INTERVAL_MS));
const maxResultChars = _nullishCoalesce(config.maxResultChars, () => ( DEFAULT_RESULT_CHARS));
function startTask(input) {
if (activeTaskCount(tasks) >= maxConcurrent) {
return `Error [agent]: Max concurrent subagents reached (${maxConcurrent}). Use wait, result, or stop before starting more.`;
}
const selected = selectAgent(config, input.agent);
if (typeof selected === "string") {
return `Error [agent]: ${selected}`;
}
const model = _nullishCoalesce(selected.definition.model, () => ( config.model));
if (!model) {
return "Error [agent]: No model configured. Provide createAgent({ model }) or an agent-specific model.";
}
const taskId = `agent_${_crypto.randomUUID.call(void 0, )}`;
const abortController = new AbortController();
const timeoutMs = _nullishCoalesce(input.timeoutMs, () => ( defaultRunTimeoutMs));
const task = {
id: taskId,
agentName: selected.name,
description: input.description,
prompt: input.prompt,
status: "running",
startTime: Date.now(),
abortController,
promise: Promise.resolve()
};
tasks.set(taskId, task);
task.timeoutId = setTimeout(() => {
stopTask(
task,
"timed_out",
`Subagent timed out after ${timeoutMs}ms.`
);
}, timeoutMs);
task.promise = (async () => {
try {
const maxTurns = _nullishCoalesce(_nullishCoalesce(selected.definition.maxTurns, () => ( config.maxTurns)), () => ( DEFAULT_MAX_TURNS));
const stopWhen = _nullishCoalesce(_nullishCoalesce(selected.definition.stopWhen, () => ( config.stopWhen)), () => ( _ai.stepCountIs.call(void 0, maxTurns)));
const result = await _ai.generateText.call(void 0, {
..._nullishCoalesce(config.settings, () => ( {})),
..._nullishCoalesce(selected.definition.settings, () => ( {})),
model,
tools: removeAgentTools(_nullishCoalesce(selected.definition.tools, () => ( config.tools))),
system: selected.definition.systemPrompt,
prompt: input.prompt,
stopWhen,
abortSignal: abortController.signal
});
if (task.status === "running") {
task.status = "completed";
task.result = result.text;
task.usage = result.usage;
task.endTime = Date.now();
}
} catch (error) {
if (task.status === "running") {
task.status = "failed";
task.error = _chunkKONXT2SFcjs.extractErrorMessage.call(void 0, error);
task.endTime = Date.now();
}
} finally {
if (task.timeoutId) {
clearTimeout(task.timeoutId);
task.timeoutId = void 0;
}
}
})();
return `Started subagent task ${taskId}.
Agent: ${selected.name}
Status: running
Use wait with taskIds ["${taskId}"] or wait for all running tasks.`;
}
async function waitForTasks(input, abortSignal) {
const targets = getWaitTargets(tasks, input.taskIds);
if (typeof targets === "string") return `Error [agent]: ${targets}`;
if (targets.length === 0) {
return "No running or selected subagent tasks to wait for.";
}
const mode = input.mode;
const timeoutMs = _nullishCoalesce(input.timeoutMs, () => ( defaultWaitTimeoutMs));
const pollIntervalMs = _nullishCoalesce(input.pollIntervalMs, () => ( defaultPollIntervalMs));
const deadline = Date.now() + timeoutMs;
while (true) {
const completed = targets.filter(isTerminal);
const done = mode === "any" ? completed.length > 0 : completed.length === targets.length;
if (done) {
return formatWaitResult(targets, mode, false, maxResultChars);
}
const remainingMs = deadline - Date.now();
if (remainingMs <= 0) {
return formatWaitResult(targets, mode, true, maxResultChars);
}
await _promises.setTimeout.call(void 0, Math.min(pollIntervalMs, remainingMs), void 0, {
signal: abortSignal
});
}
}
return markAgentTool(_ai.tool.call(void 0, {
description: _nullishCoalesce(config.description, () => ( getPrompt(config))),
inputSchema,
execute: async (input, options) => {
try {
switch (input.action) {
case "start":
return startTask(input);
case "wait":
return await waitForTasks(input, options.abortSignal);
case "status": {
const task = tasks.get(input.taskId);
return task ? formatTaskSummary(task) : `Error [agent]: Unknown task id "${input.taskId}".`;
}
case "result": {
const task = tasks.get(input.taskId);
return task ? formatTaskResult(task, maxResultChars) : `Error [agent]: Unknown task id "${input.taskId}".`;
}
case "list": {
if (tasks.size === 0) return "No subagent tasks have been started.";
return Array.from(tasks.values()).sort((a, b) => a.startTime - b.startTime).map(formatTaskSummary).join("\n\n");
}
case "stop": {
const task = tasks.get(input.taskId);
if (!task) return `Error [agent]: Unknown task id "${input.taskId}".`;
if (task.status !== "running") {
return `Task ${task.id} is already ${task.status}.`;
}
stopTask(task, "stopped", "Subagent stopped by orchestrator.");
return `Stopped subagent task ${task.id}.`;
}
}
} catch (error) {
return `Error [agent]: ${_chunkKONXT2SFcjs.extractErrorMessage.call(void 0, error)}`;
}
}
}));
}
var agent = createAgent();
exports.getPrompt = getPrompt; exports.createAgent = createAgent; exports.agent = agent;
+2
-2

@@ -5,3 +5,3 @@ "use strict";Object.defineProperty(exports, "__esModule", {value: true});

var _chunk6THYNTJFcjs = require('../chunk-6THYNTJF.cjs');
var _chunkGMQQFVQAcjs = require('../chunk-GMQQFVQA.cjs');
require('../chunk-KONXT2SF.cjs');

@@ -12,2 +12,2 @@

exports.agent = _chunk6THYNTJFcjs.agent; exports.agentPrompt = _chunk6THYNTJFcjs.getPrompt; exports.createAgent = _chunk6THYNTJFcjs.createAgent;
exports.agent = _chunkGMQQFVQAcjs.agent; exports.agentPrompt = _chunkGMQQFVQAcjs.getPrompt; exports.createAgent = _chunkGMQQFVQAcjs.createAgent;

@@ -5,3 +5,3 @@ import {

getPrompt
} from "../chunk-34XNLXFI.js";
} from "../chunk-6SEZNYRX.js";
import "../chunk-X6ZY2KFU.js";

@@ -8,0 +8,0 @@ export {

@@ -38,3 +38,3 @@ "use strict";Object.defineProperty(exports, "__esModule", {value: true});

var _chunk6THYNTJFcjs = require('./chunk-6THYNTJF.cjs');
var _chunkGMQQFVQAcjs = require('./chunk-GMQQFVQA.cjs');

@@ -189,2 +189,2 @@

exports.agent = _chunk6THYNTJFcjs.agent; exports.agentPrompt = _chunk6THYNTJFcjs.getPrompt; exports.askUser = _chunkKUFZFNPTcjs.askUser; exports.askUserPrompt = _chunkKUFZFNPTcjs.getPrompt; exports.bash = _chunkDKN6WTRYcjs.bash; exports.bashPrompt = _chunkDKN6WTRYcjs.getPrompt; exports.compactMessages = _chunkB76NYX22cjs.compactMessages; exports.createAgent = _chunk6THYNTJFcjs.createAgent; exports.createAskUser = _chunkKUFZFNPTcjs.createAskUser; exports.createBash = _chunkDKN6WTRYcjs.createBash; exports.createDiff = _chunkOYLTQJXTcjs.createDiff; exports.createEdit = _chunk6ULQG2W2cjs.createEdit; exports.createGlob = _chunkBNICFVN5cjs.createGlob; exports.createGrep = _chunkNRU2KZIMcjs.createGrep; exports.createHttpRequest = _chunk5T3SQYI4cjs.createHttpRequest; exports.createLsp = _chunkNQIV6LBHcjs.createLsp; exports.createMemory = _chunkLNAR3NJQcjs.createMemory; exports.createMultiEdit = _chunkVPV6WG5Vcjs.createMultiEdit; exports.createOutputValidator = _chunk7HFEO5BWcjs.createOutputValidator; exports.createRead = _chunkHG5T47NAcjs.createRead; exports.createSleep = _chunkJYTOARJVcjs.createSleep; exports.createTaskCreate = _chunkSFDZRLSXcjs.createTaskCreate; exports.createTaskGet = _chunkXGDE7S2Dcjs.createTaskGet; exports.createTaskList = _chunk3FT4ZPB2cjs.createTaskList; exports.createTaskUpdate = _chunkT6STO7PScjs.createTaskUpdate; exports.createToolSearch = _chunk2JBLVFB7cjs.createToolSearch; exports.createWebFetch = _chunkG6ZVJA4Vcjs.createWebFetch; exports.createWebSearch = _chunkCM3VRCNXcjs.createWebSearch; exports.createWrite = _chunkABXTBB2Ncjs.createWrite; exports.diff = _chunkOYLTQJXTcjs.diff; exports.diffPrompt = _chunkOYLTQJXTcjs.getPrompt; exports.edit = _chunk6ULQG2W2cjs.edit; exports.editPrompt = _chunk6ULQG2W2cjs.getPrompt; exports.glob = _chunkBNICFVN5cjs.glob; exports.globPrompt = _chunkBNICFVN5cjs.getPrompt; exports.grep = _chunkNRU2KZIMcjs.grep; exports.grepPrompt = _chunkNRU2KZIMcjs.getPrompt; exports.httpRequest = _chunk5T3SQYI4cjs.httpRequest; exports.httpRequestPrompt = _chunk5T3SQYI4cjs.getPrompt; exports.lsp = _chunkNQIV6LBHcjs.lsp; exports.lspPrompt = _chunkNQIV6LBHcjs.getPrompt; exports.memory = _chunkLNAR3NJQcjs.memory; exports.memoryPrompt = _chunkLNAR3NJQcjs.getPrompt; exports.multiEdit = _chunkVPV6WG5Vcjs.multiEdit; exports.multiEditPrompt = _chunkVPV6WG5Vcjs.getPrompt; exports.outputValidator = _chunk7HFEO5BWcjs.outputValidator; exports.outputValidatorPrompt = _chunk7HFEO5BWcjs.getPrompt; exports.read = _chunkHG5T47NAcjs.read; exports.readPrompt = _chunkHG5T47NAcjs.getPrompt; exports.sleep = _chunkJYTOARJVcjs.sleep; exports.sleepPrompt = _chunkJYTOARJVcjs.getPrompt; exports.taskCreate = _chunkSFDZRLSXcjs.taskCreate; exports.taskCreatePrompt = _chunkSFDZRLSXcjs.getPrompt; exports.taskGet = _chunkXGDE7S2Dcjs.taskGet; exports.taskGetPrompt = _chunkXGDE7S2Dcjs.getPrompt; exports.taskList = _chunk3FT4ZPB2cjs.taskList; exports.taskListPrompt = _chunk3FT4ZPB2cjs.getPrompt; exports.taskUpdate = _chunkT6STO7PScjs.taskUpdate; exports.taskUpdatePrompt = _chunkT6STO7PScjs.getPrompt; exports.toolSearch = _chunk2JBLVFB7cjs.toolSearch; exports.toolSearchPrompt = _chunk2JBLVFB7cjs.getPrompt; exports.webFetch = _chunkG6ZVJA4Vcjs.webFetch; exports.webFetchPrompt = _chunkG6ZVJA4Vcjs.getPrompt; exports.webSearch = _chunkCM3VRCNXcjs.webSearch; exports.webSearchPrompt = _chunkCM3VRCNXcjs.getPrompt; exports.write = _chunkABXTBB2Ncjs.write; exports.writePrompt = _chunkABXTBB2Ncjs.getPrompt;
exports.agent = _chunkGMQQFVQAcjs.agent; exports.agentPrompt = _chunkGMQQFVQAcjs.getPrompt; exports.askUser = _chunkKUFZFNPTcjs.askUser; exports.askUserPrompt = _chunkKUFZFNPTcjs.getPrompt; exports.bash = _chunkDKN6WTRYcjs.bash; exports.bashPrompt = _chunkDKN6WTRYcjs.getPrompt; exports.compactMessages = _chunkB76NYX22cjs.compactMessages; exports.createAgent = _chunkGMQQFVQAcjs.createAgent; exports.createAskUser = _chunkKUFZFNPTcjs.createAskUser; exports.createBash = _chunkDKN6WTRYcjs.createBash; exports.createDiff = _chunkOYLTQJXTcjs.createDiff; exports.createEdit = _chunk6ULQG2W2cjs.createEdit; exports.createGlob = _chunkBNICFVN5cjs.createGlob; exports.createGrep = _chunkNRU2KZIMcjs.createGrep; exports.createHttpRequest = _chunk5T3SQYI4cjs.createHttpRequest; exports.createLsp = _chunkNQIV6LBHcjs.createLsp; exports.createMemory = _chunkLNAR3NJQcjs.createMemory; exports.createMultiEdit = _chunkVPV6WG5Vcjs.createMultiEdit; exports.createOutputValidator = _chunk7HFEO5BWcjs.createOutputValidator; exports.createRead = _chunkHG5T47NAcjs.createRead; exports.createSleep = _chunkJYTOARJVcjs.createSleep; exports.createTaskCreate = _chunkSFDZRLSXcjs.createTaskCreate; exports.createTaskGet = _chunkXGDE7S2Dcjs.createTaskGet; exports.createTaskList = _chunk3FT4ZPB2cjs.createTaskList; exports.createTaskUpdate = _chunkT6STO7PScjs.createTaskUpdate; exports.createToolSearch = _chunk2JBLVFB7cjs.createToolSearch; exports.createWebFetch = _chunkG6ZVJA4Vcjs.createWebFetch; exports.createWebSearch = _chunkCM3VRCNXcjs.createWebSearch; exports.createWrite = _chunkABXTBB2Ncjs.createWrite; exports.diff = _chunkOYLTQJXTcjs.diff; exports.diffPrompt = _chunkOYLTQJXTcjs.getPrompt; exports.edit = _chunk6ULQG2W2cjs.edit; exports.editPrompt = _chunk6ULQG2W2cjs.getPrompt; exports.glob = _chunkBNICFVN5cjs.glob; exports.globPrompt = _chunkBNICFVN5cjs.getPrompt; exports.grep = _chunkNRU2KZIMcjs.grep; exports.grepPrompt = _chunkNRU2KZIMcjs.getPrompt; exports.httpRequest = _chunk5T3SQYI4cjs.httpRequest; exports.httpRequestPrompt = _chunk5T3SQYI4cjs.getPrompt; exports.lsp = _chunkNQIV6LBHcjs.lsp; exports.lspPrompt = _chunkNQIV6LBHcjs.getPrompt; exports.memory = _chunkLNAR3NJQcjs.memory; exports.memoryPrompt = _chunkLNAR3NJQcjs.getPrompt; exports.multiEdit = _chunkVPV6WG5Vcjs.multiEdit; exports.multiEditPrompt = _chunkVPV6WG5Vcjs.getPrompt; exports.outputValidator = _chunk7HFEO5BWcjs.outputValidator; exports.outputValidatorPrompt = _chunk7HFEO5BWcjs.getPrompt; exports.read = _chunkHG5T47NAcjs.read; exports.readPrompt = _chunkHG5T47NAcjs.getPrompt; exports.sleep = _chunkJYTOARJVcjs.sleep; exports.sleepPrompt = _chunkJYTOARJVcjs.getPrompt; exports.taskCreate = _chunkSFDZRLSXcjs.taskCreate; exports.taskCreatePrompt = _chunkSFDZRLSXcjs.getPrompt; exports.taskGet = _chunkXGDE7S2Dcjs.taskGet; exports.taskGetPrompt = _chunkXGDE7S2Dcjs.getPrompt; exports.taskList = _chunk3FT4ZPB2cjs.taskList; exports.taskListPrompt = _chunk3FT4ZPB2cjs.getPrompt; exports.taskUpdate = _chunkT6STO7PScjs.taskUpdate; exports.taskUpdatePrompt = _chunkT6STO7PScjs.getPrompt; exports.toolSearch = _chunk2JBLVFB7cjs.toolSearch; exports.toolSearchPrompt = _chunk2JBLVFB7cjs.getPrompt; exports.webFetch = _chunkG6ZVJA4Vcjs.webFetch; exports.webFetchPrompt = _chunkG6ZVJA4Vcjs.getPrompt; exports.webSearch = _chunkCM3VRCNXcjs.webSearch; exports.webSearchPrompt = _chunkCM3VRCNXcjs.getPrompt; exports.write = _chunkABXTBB2Ncjs.write; exports.writePrompt = _chunkABXTBB2Ncjs.getPrompt;

@@ -38,3 +38,3 @@ import {

getPrompt as getPrompt22
} from "./chunk-34XNLXFI.js";
} from "./chunk-6SEZNYRX.js";
import {

@@ -41,0 +41,0 @@ createMemory,

{
"name": "agentool",
"version": "1.5.0",
"version": "1.5.1",
"type": "module",

@@ -10,7 +10,7 @@ "description": "23 AI agent tools + context-compaction helper as standalone Vercel AI SDK modules",

"type": "git",
"url": "git+https://github.com/Z-M-Huang/agentool.git"
"url": "git+https://github.com/markhuangai/agentool.git"
},
"homepage": "https://github.com/Z-M-Huang/agentool#readme",
"homepage": "https://github.com/markhuangai/agentool#readme",
"bugs": {
"url": "https://github.com/Z-M-Huang/agentool/issues"
"url": "https://github.com/markhuangai/agentool/issues"
},

@@ -165,2 +165,3 @@ "keywords": [

"test:functional": "vitest run --project functional",
"test:provider-compat": "vitest run --project functional tests/functional/provider-compat.functional.test.ts",
"lint": "eslint src/",

@@ -187,2 +188,3 @@ "precommit": "npm run lint && npm run typecheck && npm run test:coverage"

"devDependencies": {
"@ai-sdk/anthropic": "^3.0.79",
"@ai-sdk/openai": "^3.0.50",

@@ -189,0 +191,0 @@ "@types/diff": "^7.0.0",

@@ -10,5 +10,5 @@ <div align="center">

<a href="https://www.npmjs.com/package/agentool"><img src="https://img.shields.io/npm/dm/agentool?style=flat-square&color=cb3837&logo=npm" alt="npm downloads" /></a>
<a href="https://github.com/Z-M-Huang/agentool"><img src="https://img.shields.io/github/stars/Z-M-Huang/agentool?style=flat-square&logo=github" alt="GitHub stars" /></a>
<a href="https://github.com/Z-M-Huang/agentool/issues"><img src="https://img.shields.io/github/issues/Z-M-Huang/agentool?style=flat-square&logo=github" alt="GitHub issues" /></a>
<a href="https://github.com/Z-M-Huang/agentool/blob/main/LICENSE"><img src="https://img.shields.io/github/license/Z-M-Huang/agentool?style=flat-square" alt="License" /></a>
<a href="https://github.com/markhuangai/agentool"><img src="https://img.shields.io/github/stars/markhuangai/agentool?style=flat-square&logo=github" alt="GitHub stars" /></a>
<a href="https://github.com/markhuangai/agentool/issues"><img src="https://img.shields.io/github/issues/markhuangai/agentool?style=flat-square&logo=github" alt="GitHub issues" /></a>
<a href="https://github.com/markhuangai/agentool/blob/main/LICENSE"><img src="https://img.shields.io/github/license/markhuangai/agentool?style=flat-square" alt="License" /></a>
</p>

@@ -21,3 +21,3 @@ <p>

<img src="https://img.shields.io/badge/coverage-96%25-brightgreen?style=flat-square" alt="Test Coverage" />
<img src="https://visitor-badge.laobi.icu/badge?page_id=Z-M-Huang.agentool&style=flat-square" alt="Visitors" />
<img src="https://komarev.com/ghpvc/?username=markhuangai&repo=agentool&style=flat-square&label=Visitors" alt="Visitors" />
</p>

@@ -24,0 +24,0 @@ </div>

import {
extractErrorMessage
} from "./chunk-X6ZY2KFU.js";
// src/agent/index.ts
import { generateText, stepCountIs, tool } from "ai";
import { randomUUID } from "crypto";
import { setTimeout as sleep } from "timers/promises";
// src/agent/constants.ts
var DEFAULT_AGENT_NAME = "default";
var DEFAULT_MAX_CONCURRENT = 4;
var DEFAULT_RUN_TIMEOUT_MS = 3e5;
var DEFAULT_WAIT_TIMEOUT_MS = 3e4;
var DEFAULT_POLL_INTERVAL_MS = 500;
var DEFAULT_RESULT_CHARS = 3e4;
var DEFAULT_MAX_TURNS = 20;
var terminalStatuses = /* @__PURE__ */ new Set([
"completed",
"failed",
"stopped",
"timed_out"
]);
var fallbackAgent = {
description: "General purpose subagent",
systemPrompt: "You are a focused subagent. Complete the delegated task and report concise findings back to the orchestrator."
};
// src/agent/format.ts
function isTerminal(task) {
return terminalStatuses.has(task.status);
}
function truncateResult(value, maxChars) {
if (value.length <= maxChars) return value;
const omitted = value.length - maxChars;
return `${value.slice(0, maxChars)}
... [agent result truncated - ${omitted} chars removed]`;
}
function formatUsage(usage) {
if (!usage) return "";
const parts = [
usage.inputTokens === void 0 ? void 0 : `input=${usage.inputTokens}`,
usage.outputTokens === void 0 ? void 0 : `output=${usage.outputTokens}`,
usage.totalTokens === void 0 ? void 0 : `total=${usage.totalTokens}`
].filter((part) => part !== void 0);
return parts.length > 0 ? `
Usage: ${parts.join(", ")}` : "";
}
function formatTaskSummary(task) {
const elapsedMs = (task.endTime ?? Date.now()) - task.startTime;
const label = task.description ? ` (${task.description})` : "";
const error = task.error ? `
Error: ${task.error}` : "";
return `Task ${task.id}${label}
Agent: ${task.agentName}
Status: ${task.status}
Elapsed: ${elapsedMs}ms${formatUsage(task.usage)}${error}`;
}
function formatTaskResult(task, maxResultChars) {
const summary = formatTaskSummary(task);
if (task.status === "completed") {
return `${summary}
Result:
${truncateResult(task.result ?? "", maxResultChars)}`;
}
if (task.status === "running") {
return `${summary}
Result is not ready yet. Use wait or status later.`;
}
return summary;
}
function formatWaitResult(tasks, mode, timedOut, maxResultChars) {
const completed = tasks.filter(isTerminal);
const running = tasks.filter((task) => task.status === "running");
const header = timedOut ? `Wait timed out. ${completed.length}/${tasks.length} selected task(s) finished.` : `Wait complete (${mode}). ${completed.length}/${tasks.length} selected task(s) finished.`;
const sections = completed.map((task) => formatTaskResult(task, maxResultChars));
const runningLines = running.map(
(task) => `Task ${task.id}: running${task.description ? ` (${task.description})` : ""}`
);
return [header, ...sections, ...runningLines].join("\n\n");
}
// src/agent/prompt.ts
function getPrompt(config = {}) {
const names = Object.keys(config.agents ?? {});
const registryLine = names.length > 0 ? `Configured agents: ${names.join(", ")}.` : "No named agents are configured; the built-in default agent is used.";
return `Spawn and manage parallel subagents.
Use this tool when work can be split into focused independent investigations or checks.
${registryLine}
Actions:
- start: launch a subagent in the background and return a task id immediately.
- wait: wait internally for any or all selected tasks to finish.
- status: inspect one task.
- result: read one completed task result.
- list: show known tasks.
- stop: abort a running task.
Guidelines:
- Start multiple independent subagents before waiting when parallel work helps.
- Use wait instead of repeatedly polling status.
- Subagents do not receive this agent tool recursively.
- If a result is incomplete, start a narrower follow-up subagent or investigate directly.
- Stop tasks that are no longer useful.`;
}
// src/agent/schema.ts
import { z } from "zod";
var inputSchema = z.discriminatedUnion("action", [
z.object({
action: z.literal("start"),
agent: z.string().optional().describe("Configured agent name to run"),
prompt: z.string().describe("User prompt for the subagent"),
description: z.string().optional().describe("Short task label"),
timeoutMs: z.number().int().positive().optional().describe("Run timeout in milliseconds")
}),
z.object({
action: z.literal("wait"),
taskIds: z.array(z.string()).optional().describe("Task ids to wait for. Defaults to all running tasks."),
mode: z.enum(["all", "any"]).optional().default("all").describe("Wait for all selected tasks or the first selected task"),
timeoutMs: z.number().int().nonnegative().optional().describe("Wait timeout in milliseconds"),
pollIntervalMs: z.number().int().positive().optional().describe("Internal polling interval in milliseconds")
}),
z.object({
action: z.literal("status"),
taskId: z.string().describe("Task id to inspect")
}),
z.object({
action: z.literal("result"),
taskId: z.string().describe("Task id to read")
}),
z.object({
action: z.literal("list")
}),
z.object({
action: z.literal("stop"),
taskId: z.string().describe("Task id to stop")
})
]);
// src/agent/tasks.ts
function activeTaskCount(tasks) {
let count = 0;
for (const task of tasks.values()) {
if (task.status === "running") count++;
}
return count;
}
function selectAgent(config, requestedName) {
const registry = config.agents ?? {};
const registryNames = Object.keys(registry);
const name = requestedName ?? config.defaultAgent ?? registryNames[0] ?? DEFAULT_AGENT_NAME;
const definition = registry[name] ?? (name === DEFAULT_AGENT_NAME && registryNames.length === 0 ? fallbackAgent : void 0);
if (!definition) {
const available = registryNames.length > 0 ? registryNames.join(", ") : DEFAULT_AGENT_NAME;
return `Unknown agent "${name}". Available agents: ${available}.`;
}
return { name, definition };
}
function getWaitTargets(tasks, taskIds) {
if (taskIds && taskIds.length > 0) {
const selected = [];
const missing = [];
for (const taskId of taskIds) {
const task = tasks.get(taskId);
if (task) selected.push(task);
else missing.push(taskId);
}
if (missing.length > 0) {
return `Unknown task id(s): ${missing.join(", ")}.`;
}
return selected;
}
return Array.from(tasks.values()).filter((task) => task.status === "running");
}
function stopTask(task, status, error) {
if (task.status !== "running") return;
task.status = status;
task.error = error;
task.endTime = Date.now();
if (task.timeoutId) {
clearTimeout(task.timeoutId);
task.timeoutId = void 0;
}
task.abortController.abort();
}
// src/agent/tools.ts
var AGENT_TOOL_NAME = "agent";
var agentTools = /* @__PURE__ */ new WeakSet();
function markAgentTool(agentTool) {
agentTools.add(agentTool);
return agentTool;
}
function isMarkedAgentTool(value) {
return typeof value === "object" && value !== null && agentTools.has(value);
}
function removeAgentTools(tools) {
if (!tools) return tools;
const toolEntries = Object.entries(tools);
const entries = toolEntries.filter(
([name, value]) => name !== AGENT_TOOL_NAME && !isMarkedAgentTool(value)
);
if (entries.length === toolEntries.length) return tools;
if (entries.length === 0) return void 0;
return Object.fromEntries(entries);
}
// src/agent/index.ts
function createAgent(config = {}) {
const tasks = /* @__PURE__ */ new Map();
const maxConcurrent = config.maxConcurrent ?? DEFAULT_MAX_CONCURRENT;
const defaultRunTimeoutMs = config.defaultTimeoutMs ?? DEFAULT_RUN_TIMEOUT_MS;
const defaultWaitTimeoutMs = config.defaultWaitTimeoutMs ?? DEFAULT_WAIT_TIMEOUT_MS;
const defaultPollIntervalMs = config.defaultPollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
const maxResultChars = config.maxResultChars ?? DEFAULT_RESULT_CHARS;
function startTask(input) {
if (activeTaskCount(tasks) >= maxConcurrent) {
return `Error [agent]: Max concurrent subagents reached (${maxConcurrent}). Use wait, result, or stop before starting more.`;
}
const selected = selectAgent(config, input.agent);
if (typeof selected === "string") {
return `Error [agent]: ${selected}`;
}
const model = selected.definition.model ?? config.model;
if (!model) {
return "Error [agent]: No model configured. Provide createAgent({ model }) or an agent-specific model.";
}
const taskId = `agent_${randomUUID()}`;
const abortController = new AbortController();
const timeoutMs = input.timeoutMs ?? defaultRunTimeoutMs;
const task = {
id: taskId,
agentName: selected.name,
description: input.description,
prompt: input.prompt,
status: "running",
startTime: Date.now(),
abortController,
promise: Promise.resolve()
};
tasks.set(taskId, task);
task.timeoutId = setTimeout(() => {
stopTask(
task,
"timed_out",
`Subagent timed out after ${timeoutMs}ms.`
);
}, timeoutMs);
task.promise = (async () => {
try {
const maxTurns = selected.definition.maxTurns ?? config.maxTurns ?? DEFAULT_MAX_TURNS;
const stopWhen = selected.definition.stopWhen ?? config.stopWhen ?? stepCountIs(maxTurns);
const result = await generateText({
...config.settings ?? {},
...selected.definition.settings ?? {},
model,
tools: removeAgentTools(selected.definition.tools ?? config.tools),
system: selected.definition.systemPrompt,
prompt: input.prompt,
stopWhen,
abortSignal: abortController.signal
});
if (task.status === "running") {
task.status = "completed";
task.result = result.text;
task.usage = result.usage;
task.endTime = Date.now();
}
} catch (error) {
if (task.status === "running") {
task.status = "failed";
task.error = extractErrorMessage(error);
task.endTime = Date.now();
}
} finally {
if (task.timeoutId) {
clearTimeout(task.timeoutId);
task.timeoutId = void 0;
}
}
})();
return `Started subagent task ${taskId}.
Agent: ${selected.name}
Status: running
Use wait with taskIds ["${taskId}"] or wait for all running tasks.`;
}
async function waitForTasks(input, abortSignal) {
const targets = getWaitTargets(tasks, input.taskIds);
if (typeof targets === "string") return `Error [agent]: ${targets}`;
if (targets.length === 0) {
return "No running or selected subagent tasks to wait for.";
}
const mode = input.mode;
const timeoutMs = input.timeoutMs ?? defaultWaitTimeoutMs;
const pollIntervalMs = input.pollIntervalMs ?? defaultPollIntervalMs;
const deadline = Date.now() + timeoutMs;
while (true) {
const completed = targets.filter(isTerminal);
const done = mode === "any" ? completed.length > 0 : completed.length === targets.length;
if (done) {
return formatWaitResult(targets, mode, false, maxResultChars);
}
const remainingMs = deadline - Date.now();
if (remainingMs <= 0) {
return formatWaitResult(targets, mode, true, maxResultChars);
}
await sleep(Math.min(pollIntervalMs, remainingMs), void 0, {
signal: abortSignal
});
}
}
return markAgentTool(tool({
description: config.description ?? getPrompt(config),
inputSchema,
execute: async (input, options) => {
try {
switch (input.action) {
case "start":
return startTask(input);
case "wait":
return await waitForTasks(input, options.abortSignal);
case "status": {
const task = tasks.get(input.taskId);
return task ? formatTaskSummary(task) : `Error [agent]: Unknown task id "${input.taskId}".`;
}
case "result": {
const task = tasks.get(input.taskId);
return task ? formatTaskResult(task, maxResultChars) : `Error [agent]: Unknown task id "${input.taskId}".`;
}
case "list": {
if (tasks.size === 0) return "No subagent tasks have been started.";
return Array.from(tasks.values()).sort((a, b) => a.startTime - b.startTime).map(formatTaskSummary).join("\n\n");
}
case "stop": {
const task = tasks.get(input.taskId);
if (!task) return `Error [agent]: Unknown task id "${input.taskId}".`;
if (task.status !== "running") {
return `Task ${task.id} is already ${task.status}.`;
}
stopTask(task, "stopped", "Subagent stopped by orchestrator.");
return `Stopped subagent task ${task.id}.`;
}
}
} catch (error) {
return `Error [agent]: ${extractErrorMessage(error)}`;
}
}
}));
}
var agent = createAgent();
export {
getPrompt,
createAgent,
agent
};
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
var _chunkKONXT2SFcjs = require('./chunk-KONXT2SF.cjs');
// src/agent/index.ts
var _ai = require('ai');
var _crypto = require('crypto');
var _promises = require('timers/promises');
// src/agent/constants.ts
var DEFAULT_AGENT_NAME = "default";
var DEFAULT_MAX_CONCURRENT = 4;
var DEFAULT_RUN_TIMEOUT_MS = 3e5;
var DEFAULT_WAIT_TIMEOUT_MS = 3e4;
var DEFAULT_POLL_INTERVAL_MS = 500;
var DEFAULT_RESULT_CHARS = 3e4;
var DEFAULT_MAX_TURNS = 20;
var terminalStatuses = /* @__PURE__ */ new Set([
"completed",
"failed",
"stopped",
"timed_out"
]);
var fallbackAgent = {
description: "General purpose subagent",
systemPrompt: "You are a focused subagent. Complete the delegated task and report concise findings back to the orchestrator."
};
// src/agent/format.ts
function isTerminal(task) {
return terminalStatuses.has(task.status);
}
function truncateResult(value, maxChars) {
if (value.length <= maxChars) return value;
const omitted = value.length - maxChars;
return `${value.slice(0, maxChars)}
... [agent result truncated - ${omitted} chars removed]`;
}
function formatUsage(usage) {
if (!usage) return "";
const parts = [
usage.inputTokens === void 0 ? void 0 : `input=${usage.inputTokens}`,
usage.outputTokens === void 0 ? void 0 : `output=${usage.outputTokens}`,
usage.totalTokens === void 0 ? void 0 : `total=${usage.totalTokens}`
].filter((part) => part !== void 0);
return parts.length > 0 ? `
Usage: ${parts.join(", ")}` : "";
}
function formatTaskSummary(task) {
const elapsedMs = (_nullishCoalesce(task.endTime, () => ( Date.now()))) - task.startTime;
const label = task.description ? ` (${task.description})` : "";
const error = task.error ? `
Error: ${task.error}` : "";
return `Task ${task.id}${label}
Agent: ${task.agentName}
Status: ${task.status}
Elapsed: ${elapsedMs}ms${formatUsage(task.usage)}${error}`;
}
function formatTaskResult(task, maxResultChars) {
const summary = formatTaskSummary(task);
if (task.status === "completed") {
return `${summary}
Result:
${truncateResult(_nullishCoalesce(task.result, () => ( "")), maxResultChars)}`;
}
if (task.status === "running") {
return `${summary}
Result is not ready yet. Use wait or status later.`;
}
return summary;
}
function formatWaitResult(tasks, mode, timedOut, maxResultChars) {
const completed = tasks.filter(isTerminal);
const running = tasks.filter((task) => task.status === "running");
const header = timedOut ? `Wait timed out. ${completed.length}/${tasks.length} selected task(s) finished.` : `Wait complete (${mode}). ${completed.length}/${tasks.length} selected task(s) finished.`;
const sections = completed.map((task) => formatTaskResult(task, maxResultChars));
const runningLines = running.map(
(task) => `Task ${task.id}: running${task.description ? ` (${task.description})` : ""}`
);
return [header, ...sections, ...runningLines].join("\n\n");
}
// src/agent/prompt.ts
function getPrompt(config = {}) {
const names = Object.keys(_nullishCoalesce(config.agents, () => ( {})));
const registryLine = names.length > 0 ? `Configured agents: ${names.join(", ")}.` : "No named agents are configured; the built-in default agent is used.";
return `Spawn and manage parallel subagents.
Use this tool when work can be split into focused independent investigations or checks.
${registryLine}
Actions:
- start: launch a subagent in the background and return a task id immediately.
- wait: wait internally for any or all selected tasks to finish.
- status: inspect one task.
- result: read one completed task result.
- list: show known tasks.
- stop: abort a running task.
Guidelines:
- Start multiple independent subagents before waiting when parallel work helps.
- Use wait instead of repeatedly polling status.
- Subagents do not receive this agent tool recursively.
- If a result is incomplete, start a narrower follow-up subagent or investigate directly.
- Stop tasks that are no longer useful.`;
}
// src/agent/schema.ts
var _zod = require('zod');
var inputSchema = _zod.z.discriminatedUnion("action", [
_zod.z.object({
action: _zod.z.literal("start"),
agent: _zod.z.string().optional().describe("Configured agent name to run"),
prompt: _zod.z.string().describe("User prompt for the subagent"),
description: _zod.z.string().optional().describe("Short task label"),
timeoutMs: _zod.z.number().int().positive().optional().describe("Run timeout in milliseconds")
}),
_zod.z.object({
action: _zod.z.literal("wait"),
taskIds: _zod.z.array(_zod.z.string()).optional().describe("Task ids to wait for. Defaults to all running tasks."),
mode: _zod.z.enum(["all", "any"]).optional().default("all").describe("Wait for all selected tasks or the first selected task"),
timeoutMs: _zod.z.number().int().nonnegative().optional().describe("Wait timeout in milliseconds"),
pollIntervalMs: _zod.z.number().int().positive().optional().describe("Internal polling interval in milliseconds")
}),
_zod.z.object({
action: _zod.z.literal("status"),
taskId: _zod.z.string().describe("Task id to inspect")
}),
_zod.z.object({
action: _zod.z.literal("result"),
taskId: _zod.z.string().describe("Task id to read")
}),
_zod.z.object({
action: _zod.z.literal("list")
}),
_zod.z.object({
action: _zod.z.literal("stop"),
taskId: _zod.z.string().describe("Task id to stop")
})
]);
// src/agent/tasks.ts
function activeTaskCount(tasks) {
let count = 0;
for (const task of tasks.values()) {
if (task.status === "running") count++;
}
return count;
}
function selectAgent(config, requestedName) {
const registry = _nullishCoalesce(config.agents, () => ( {}));
const registryNames = Object.keys(registry);
const name = _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(requestedName, () => ( config.defaultAgent)), () => ( registryNames[0])), () => ( DEFAULT_AGENT_NAME));
const definition = _nullishCoalesce(registry[name], () => ( (name === DEFAULT_AGENT_NAME && registryNames.length === 0 ? fallbackAgent : void 0)));
if (!definition) {
const available = registryNames.length > 0 ? registryNames.join(", ") : DEFAULT_AGENT_NAME;
return `Unknown agent "${name}". Available agents: ${available}.`;
}
return { name, definition };
}
function getWaitTargets(tasks, taskIds) {
if (taskIds && taskIds.length > 0) {
const selected = [];
const missing = [];
for (const taskId of taskIds) {
const task = tasks.get(taskId);
if (task) selected.push(task);
else missing.push(taskId);
}
if (missing.length > 0) {
return `Unknown task id(s): ${missing.join(", ")}.`;
}
return selected;
}
return Array.from(tasks.values()).filter((task) => task.status === "running");
}
function stopTask(task, status, error) {
if (task.status !== "running") return;
task.status = status;
task.error = error;
task.endTime = Date.now();
if (task.timeoutId) {
clearTimeout(task.timeoutId);
task.timeoutId = void 0;
}
task.abortController.abort();
}
// src/agent/tools.ts
var AGENT_TOOL_NAME = "agent";
var agentTools = /* @__PURE__ */ new WeakSet();
function markAgentTool(agentTool) {
agentTools.add(agentTool);
return agentTool;
}
function isMarkedAgentTool(value) {
return typeof value === "object" && value !== null && agentTools.has(value);
}
function removeAgentTools(tools) {
if (!tools) return tools;
const toolEntries = Object.entries(tools);
const entries = toolEntries.filter(
([name, value]) => name !== AGENT_TOOL_NAME && !isMarkedAgentTool(value)
);
if (entries.length === toolEntries.length) return tools;
if (entries.length === 0) return void 0;
return Object.fromEntries(entries);
}
// src/agent/index.ts
function createAgent(config = {}) {
const tasks = /* @__PURE__ */ new Map();
const maxConcurrent = _nullishCoalesce(config.maxConcurrent, () => ( DEFAULT_MAX_CONCURRENT));
const defaultRunTimeoutMs = _nullishCoalesce(config.defaultTimeoutMs, () => ( DEFAULT_RUN_TIMEOUT_MS));
const defaultWaitTimeoutMs = _nullishCoalesce(config.defaultWaitTimeoutMs, () => ( DEFAULT_WAIT_TIMEOUT_MS));
const defaultPollIntervalMs = _nullishCoalesce(config.defaultPollIntervalMs, () => ( DEFAULT_POLL_INTERVAL_MS));
const maxResultChars = _nullishCoalesce(config.maxResultChars, () => ( DEFAULT_RESULT_CHARS));
function startTask(input) {
if (activeTaskCount(tasks) >= maxConcurrent) {
return `Error [agent]: Max concurrent subagents reached (${maxConcurrent}). Use wait, result, or stop before starting more.`;
}
const selected = selectAgent(config, input.agent);
if (typeof selected === "string") {
return `Error [agent]: ${selected}`;
}
const model = _nullishCoalesce(selected.definition.model, () => ( config.model));
if (!model) {
return "Error [agent]: No model configured. Provide createAgent({ model }) or an agent-specific model.";
}
const taskId = `agent_${_crypto.randomUUID.call(void 0, )}`;
const abortController = new AbortController();
const timeoutMs = _nullishCoalesce(input.timeoutMs, () => ( defaultRunTimeoutMs));
const task = {
id: taskId,
agentName: selected.name,
description: input.description,
prompt: input.prompt,
status: "running",
startTime: Date.now(),
abortController,
promise: Promise.resolve()
};
tasks.set(taskId, task);
task.timeoutId = setTimeout(() => {
stopTask(
task,
"timed_out",
`Subagent timed out after ${timeoutMs}ms.`
);
}, timeoutMs);
task.promise = (async () => {
try {
const maxTurns = _nullishCoalesce(_nullishCoalesce(selected.definition.maxTurns, () => ( config.maxTurns)), () => ( DEFAULT_MAX_TURNS));
const stopWhen = _nullishCoalesce(_nullishCoalesce(selected.definition.stopWhen, () => ( config.stopWhen)), () => ( _ai.stepCountIs.call(void 0, maxTurns)));
const result = await _ai.generateText.call(void 0, {
..._nullishCoalesce(config.settings, () => ( {})),
..._nullishCoalesce(selected.definition.settings, () => ( {})),
model,
tools: removeAgentTools(_nullishCoalesce(selected.definition.tools, () => ( config.tools))),
system: selected.definition.systemPrompt,
prompt: input.prompt,
stopWhen,
abortSignal: abortController.signal
});
if (task.status === "running") {
task.status = "completed";
task.result = result.text;
task.usage = result.usage;
task.endTime = Date.now();
}
} catch (error) {
if (task.status === "running") {
task.status = "failed";
task.error = _chunkKONXT2SFcjs.extractErrorMessage.call(void 0, error);
task.endTime = Date.now();
}
} finally {
if (task.timeoutId) {
clearTimeout(task.timeoutId);
task.timeoutId = void 0;
}
}
})();
return `Started subagent task ${taskId}.
Agent: ${selected.name}
Status: running
Use wait with taskIds ["${taskId}"] or wait for all running tasks.`;
}
async function waitForTasks(input, abortSignal) {
const targets = getWaitTargets(tasks, input.taskIds);
if (typeof targets === "string") return `Error [agent]: ${targets}`;
if (targets.length === 0) {
return "No running or selected subagent tasks to wait for.";
}
const mode = input.mode;
const timeoutMs = _nullishCoalesce(input.timeoutMs, () => ( defaultWaitTimeoutMs));
const pollIntervalMs = _nullishCoalesce(input.pollIntervalMs, () => ( defaultPollIntervalMs));
const deadline = Date.now() + timeoutMs;
while (true) {
const completed = targets.filter(isTerminal);
const done = mode === "any" ? completed.length > 0 : completed.length === targets.length;
if (done) {
return formatWaitResult(targets, mode, false, maxResultChars);
}
const remainingMs = deadline - Date.now();
if (remainingMs <= 0) {
return formatWaitResult(targets, mode, true, maxResultChars);
}
await _promises.setTimeout.call(void 0, Math.min(pollIntervalMs, remainingMs), void 0, {
signal: abortSignal
});
}
}
return markAgentTool(_ai.tool.call(void 0, {
description: _nullishCoalesce(config.description, () => ( getPrompt(config))),
inputSchema,
execute: async (input, options) => {
try {
switch (input.action) {
case "start":
return startTask(input);
case "wait":
return await waitForTasks(input, options.abortSignal);
case "status": {
const task = tasks.get(input.taskId);
return task ? formatTaskSummary(task) : `Error [agent]: Unknown task id "${input.taskId}".`;
}
case "result": {
const task = tasks.get(input.taskId);
return task ? formatTaskResult(task, maxResultChars) : `Error [agent]: Unknown task id "${input.taskId}".`;
}
case "list": {
if (tasks.size === 0) return "No subagent tasks have been started.";
return Array.from(tasks.values()).sort((a, b) => a.startTime - b.startTime).map(formatTaskSummary).join("\n\n");
}
case "stop": {
const task = tasks.get(input.taskId);
if (!task) return `Error [agent]: Unknown task id "${input.taskId}".`;
if (task.status !== "running") {
return `Task ${task.id} is already ${task.status}.`;
}
stopTask(task, "stopped", "Subagent stopped by orchestrator.");
return `Stopped subagent task ${task.id}.`;
}
}
} catch (error) {
return `Error [agent]: ${_chunkKONXT2SFcjs.extractErrorMessage.call(void 0, error)}`;
}
}
}));
}
var agent = createAgent();
exports.getPrompt = getPrompt; exports.createAgent = createAgent; exports.agent = agent;