| 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; |
@@ -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 { |
+2
-2
@@ -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; |
+1
-1
@@ -38,3 +38,3 @@ import { | ||
| getPrompt as getPrompt22 | ||
| } from "./chunk-34XNLXFI.js"; | ||
| } from "./chunk-6SEZNYRX.js"; | ||
| import { | ||
@@ -41,0 +41,0 @@ createMemory, |
+6
-4
| { | ||
| "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", |
+4
-4
@@ -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; |
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
442747
0.83%8903
1.33%16
6.67%