Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6bed8f20b5 | ||
|
|
dc45a99b04 |
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ztimson/ai-utils",
|
"name": "@ztimson/ai-utils",
|
||||||
"version": "1.6.12",
|
"version": "1.7.0",
|
||||||
"description": "AI Utility library",
|
"description": "AI Utility library",
|
||||||
"author": "Zak Timson",
|
"author": "Zak Timson",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
+19
-13
@@ -19,6 +19,13 @@ const PDF_OCR_PAGE_THRESHOLD = 12; // above this many pages, OCR scanned pages i
|
|||||||
export type AnthropicConfig = {proto: 'anthropic', token: string | string[]};
|
export type AnthropicConfig = {proto: 'anthropic', token: string | string[]};
|
||||||
export type OpenAiConfig = {proto: 'openai', host?: string, token: string | string[]};
|
export type OpenAiConfig = {proto: 'openai', host?: string, token: string | string[]};
|
||||||
|
|
||||||
|
export type AgentRef = {
|
||||||
|
name: string;
|
||||||
|
description?: string;
|
||||||
|
delegate?: boolean;
|
||||||
|
fn: () => Agent | null | Promise<Agent | null>;
|
||||||
|
}
|
||||||
|
|
||||||
export type Agent = {
|
export type Agent = {
|
||||||
name: string;
|
name: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
@@ -29,7 +36,7 @@ export type Agent = {
|
|||||||
skills?: Skill[] | null;
|
skills?: Skill[] | null;
|
||||||
tools?: AiTool[] | null;
|
tools?: AiTool[] | null;
|
||||||
mcp?: McpServer[] | null;
|
mcp?: McpServer[] | null;
|
||||||
agents?: string[] | null;
|
agents?: AgentRef[] | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type LLMFile = {
|
export type LLMFile = {
|
||||||
@@ -106,8 +113,8 @@ export type LLMRequest = {
|
|||||||
skills?: Skill[];
|
skills?: Skill[];
|
||||||
/** MCP servers to connect and expose as tools */
|
/** MCP servers to connect and expose as tools */
|
||||||
mcp?: McpServer[];
|
mcp?: McpServer[];
|
||||||
/** Subagents exposed as delegatable/wrapped tools */
|
/** Subagents exposed as delegatable/wrapped tools, resolved lazily via their `fn` */
|
||||||
agents?: Agent[];
|
agents?: AgentRef[];
|
||||||
/** Attach files to request */
|
/** Attach files to request */
|
||||||
files?: LLMFile[];
|
files?: LLMFile[];
|
||||||
/** @internal recursion guard for nested agent delegation */
|
/** @internal recursion guard for nested agent delegation */
|
||||||
@@ -265,22 +272,21 @@ class LLM {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private setupAgent(agents: Agent[] = [], allAgents: Agent[], history: LLMMessage[], aborts: ((keep?: boolean) => void)[], depth = 0, delegateState: {resp: string | null}): AiTool[] {
|
private setupAgent(stubs: AgentRef[] = [], history: LLMMessage[], aborts: ((keep?: boolean) => void)[], depth = 0, delegateState: {resp: string | null}): AiTool[] {
|
||||||
return agents.map(a => {
|
return stubs.map(stub => {
|
||||||
const toolName = `${a.delegate ? '' : 'sub'}agent_${snakeCase(a.name)}`;
|
const toolName = `${stub.delegate ? '' : 'sub'}agent_${snakeCase(stub.name)}`;
|
||||||
return {
|
return {
|
||||||
name: toolName,
|
name: toolName,
|
||||||
description: `${a.delegate ? 'Delegate to ' : ''}Subagent: ${a.description || a.name}`,
|
description: `${stub.delegate ? 'Delegate to ' : ''}Subagent: ${stub.description || stub.name}`,
|
||||||
args: clean<any>({
|
args: clean<any>({
|
||||||
context: !a.delegate ? {type: 'string', description: 'Summary of related messages, samples, files, etc...', required: true} : undefined,
|
context: !stub.delegate ? {type: 'string', description: 'Summary of related messages, samples, files, etc...', required: true} : undefined,
|
||||||
instructions: {type: 'string', description: 'Detailed instructions for subagent to complete', required: true},
|
instructions: {type: 'string', description: 'Detailed instructions for subagent to complete', required: true},
|
||||||
}),
|
}),
|
||||||
fn: async (args: any, stream: any, ai: any, id?: string) => {
|
fn: async (args: any, stream: any, ai: any, id?: string) => {
|
||||||
if(depth >= MAX_AGENT_DEPTH) return 'Max agent delegation depth exceeded';
|
if(depth >= MAX_AGENT_DEPTH) return 'Max agent delegation depth exceeded';
|
||||||
|
|
||||||
const nested = (a.agents || [])
|
const a = await stub.fn();
|
||||||
.map(name => allAgents.find(x => x.name === name))
|
if(!a) return `Agent "${stub.name}" could not be resolved`;
|
||||||
.filter((x): x is Agent => !!x && x.name !== a.name);
|
|
||||||
|
|
||||||
const q = a.delegate ? '' : `${args.instructions}${args.context ? `\n\n<context>${args.context}</context>` : ''}`;
|
const q = a.delegate ? '' : `${args.instructions}${args.context ? `\n\n<context>${args.context}</context>` : ''}`;
|
||||||
|
|
||||||
@@ -297,7 +303,7 @@ ${a.system}`,
|
|||||||
mcp: a.mcp || undefined,
|
mcp: a.mcp || undefined,
|
||||||
skills: a.skills || undefined,
|
skills: a.skills || undefined,
|
||||||
tools: a.tools || undefined,
|
tools: a.tools || undefined,
|
||||||
agents: nested,
|
agents: a.agents || [],
|
||||||
_agentDepth: depth + 1,
|
_agentDepth: depth + 1,
|
||||||
} as any);
|
} as any);
|
||||||
aborts.push(request.abort);
|
aborts.push(request.abort);
|
||||||
@@ -451,7 +457,7 @@ ${a.system}`,
|
|||||||
// Agents
|
// Agents
|
||||||
const agents = options.agents || this.ai.options?.llm?.agents;
|
const agents = options.agents || this.ai.options?.llm?.agents;
|
||||||
const delegateState: {resp: string | null} = {resp: null};
|
const delegateState: {resp: string | null} = {resp: null};
|
||||||
if(agents?.length) tools.push(...this.setupAgent(agents, agents, history, nestedAborts, options._agentDepth || 0, delegateState));
|
if(agents?.length) tools.push(...this.setupAgent(agents, history, nestedAborts, options._agentDepth || 0, delegateState));
|
||||||
|
|
||||||
// Memory
|
// Memory
|
||||||
const mem = MemoryManager.normalize(options.memory);
|
const mem = MemoryManager.normalize(options.memory);
|
||||||
|
|||||||
Reference in New Issue
Block a user