@alveus-ai/std 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/basic-chat.d.ts +80 -0
- package/dist/agents/basic-chat.d.ts.map +1 -0
- package/dist/agents/basic-chat.js +91 -0
- package/dist/agents/basic-chat.js.map +1 -0
- package/dist/agents/index.d.ts +8 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +14 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/react.d.ts +153 -0
- package/dist/agents/react.d.ts.map +1 -0
- package/dist/agents/react.js +298 -0
- package/dist/agents/react.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/history.d.ts +109 -0
- package/dist/memory/history.d.ts.map +1 -0
- package/dist/memory/history.js +140 -0
- package/dist/memory/history.js.map +1 -0
- package/dist/memory/index.d.ts +7 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +7 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/patterns/approval.d.ts +151 -0
- package/dist/patterns/approval.d.ts.map +1 -0
- package/dist/patterns/approval.js +183 -0
- package/dist/patterns/approval.js.map +1 -0
- package/dist/patterns/index.d.ts +7 -0
- package/dist/patterns/index.d.ts.map +1 -0
- package/dist/patterns/index.js +7 -0
- package/dist/patterns/index.js.map +1 -0
- package/package.json +45 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Basic Chat Agent Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates reusable chat agents with a configurable system prompt.
|
|
5
|
+
* The agent is model-agnostic - it works with any LLM provider.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* // Create a helpful assistant
|
|
10
|
+
* const assistant = createChatAgent('You are a helpful assistant.');
|
|
11
|
+
*
|
|
12
|
+
* // Create a code reviewer with specific model
|
|
13
|
+
* const reviewer = createChatAgent(
|
|
14
|
+
* 'You are a senior engineer reviewing code for bugs and improvements.',
|
|
15
|
+
* { model: 'gpt-4o', provider: 'openai' }
|
|
16
|
+
* );
|
|
17
|
+
*
|
|
18
|
+
* // Execute via runtime
|
|
19
|
+
* const result = await runtime.execute({
|
|
20
|
+
* hash: assistant.definition.hash,
|
|
21
|
+
* state: {},
|
|
22
|
+
* event: { message: 'Hello, how can you help me?' }
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
import type { ChatOptions, ExecutionContext } from '@alveus-ai/core';
|
|
27
|
+
/**
|
|
28
|
+
* Input event for chat agents
|
|
29
|
+
*/
|
|
30
|
+
export interface ChatInput {
|
|
31
|
+
/** The user's message */
|
|
32
|
+
message: string;
|
|
33
|
+
/** Optional conversation history */
|
|
34
|
+
history?: Array<{
|
|
35
|
+
role: 'user' | 'assistant';
|
|
36
|
+
content: string;
|
|
37
|
+
}>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Output from chat agents
|
|
41
|
+
*/
|
|
42
|
+
export interface ChatOutput {
|
|
43
|
+
/** The assistant's reply */
|
|
44
|
+
reply: string;
|
|
45
|
+
/** Provider used for this response */
|
|
46
|
+
provider?: string;
|
|
47
|
+
/** Model used for this response */
|
|
48
|
+
model?: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Options for creating a chat agent
|
|
52
|
+
*/
|
|
53
|
+
export interface ChatAgentOptions extends ChatOptions {
|
|
54
|
+
/** Name for the agent (for debugging/logging) */
|
|
55
|
+
name?: string;
|
|
56
|
+
/** Description of the agent's purpose */
|
|
57
|
+
description?: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Create a chat agent with a configurable system prompt
|
|
61
|
+
*
|
|
62
|
+
* @param systemPrompt - The system prompt defining the agent's behavior
|
|
63
|
+
* @param options - Optional configuration for provider, model, etc.
|
|
64
|
+
* @returns An Agent that can be executed via any Alveus runtime
|
|
65
|
+
*/
|
|
66
|
+
export declare function createChatAgent(systemPrompt: string, options?: ChatAgentOptions): import("@alveus-ai/core").Agent<Record<string, unknown>, ChatInput, ExecutionContext, ChatOutput>;
|
|
67
|
+
/**
|
|
68
|
+
* Create a JSON-structured chat agent
|
|
69
|
+
*
|
|
70
|
+
* Forces the LLM to respond with valid JSON, useful for structured outputs.
|
|
71
|
+
*
|
|
72
|
+
* @param systemPrompt - The system prompt (should describe the expected JSON format)
|
|
73
|
+
* @param options - Optional configuration
|
|
74
|
+
* @returns An Agent that returns structured JSON responses
|
|
75
|
+
*/
|
|
76
|
+
export declare function createJsonChatAgent<T = unknown>(systemPrompt: string, options?: ChatAgentOptions): import("@alveus-ai/core").Agent<Record<string, unknown>, ChatInput, ExecutionContext, {
|
|
77
|
+
data: T;
|
|
78
|
+
raw: string;
|
|
79
|
+
}>;
|
|
80
|
+
//# sourceMappingURL=basic-chat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"basic-chat.d.ts","sourceRoot":"","sources":["../../src/agents/basic-chat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC;IAEhB,oCAAoC;IACpC,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClE;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IAEd,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,mCAAmC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,qGAoCnF;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,GAAG,OAAO,EAC7C,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,gBAAqB;UAST,CAAC;SAAO,MAAM;GA2BpC"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Basic Chat Agent Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates reusable chat agents with a configurable system prompt.
|
|
5
|
+
* The agent is model-agnostic - it works with any LLM provider.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* // Create a helpful assistant
|
|
10
|
+
* const assistant = createChatAgent('You are a helpful assistant.');
|
|
11
|
+
*
|
|
12
|
+
* // Create a code reviewer with specific model
|
|
13
|
+
* const reviewer = createChatAgent(
|
|
14
|
+
* 'You are a senior engineer reviewing code for bugs and improvements.',
|
|
15
|
+
* { model: 'gpt-4o', provider: 'openai' }
|
|
16
|
+
* );
|
|
17
|
+
*
|
|
18
|
+
* // Execute via runtime
|
|
19
|
+
* const result = await runtime.execute({
|
|
20
|
+
* hash: assistant.definition.hash,
|
|
21
|
+
* state: {},
|
|
22
|
+
* event: { message: 'Hello, how can you help me?' }
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
import { agent$ } from '@alveus-ai/core';
|
|
27
|
+
/**
|
|
28
|
+
* Create a chat agent with a configurable system prompt
|
|
29
|
+
*
|
|
30
|
+
* @param systemPrompt - The system prompt defining the agent's behavior
|
|
31
|
+
* @param options - Optional configuration for provider, model, etc.
|
|
32
|
+
* @returns An Agent that can be executed via any Alveus runtime
|
|
33
|
+
*/
|
|
34
|
+
export function createChatAgent(systemPrompt, options = {}) {
|
|
35
|
+
const { name, description, ...chatOptions } = options;
|
|
36
|
+
return agent$(async (_state, event, ctx) => {
|
|
37
|
+
// Build the message array
|
|
38
|
+
const messages = [
|
|
39
|
+
{ role: 'system', content: systemPrompt },
|
|
40
|
+
];
|
|
41
|
+
// Add conversation history if provided
|
|
42
|
+
if (event.history) {
|
|
43
|
+
messages.push(...event.history);
|
|
44
|
+
}
|
|
45
|
+
// Add the current user message
|
|
46
|
+
messages.push({ role: 'user', content: event.message });
|
|
47
|
+
// Generate response using the injected LLM capability
|
|
48
|
+
const reply = await ctx.llm.chat(messages, chatOptions);
|
|
49
|
+
return {
|
|
50
|
+
reply,
|
|
51
|
+
provider: chatOptions.provider,
|
|
52
|
+
model: chatOptions.model,
|
|
53
|
+
};
|
|
54
|
+
}, {
|
|
55
|
+
name: name || 'chat-agent',
|
|
56
|
+
description: description || 'A basic chat agent',
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Create a JSON-structured chat agent
|
|
61
|
+
*
|
|
62
|
+
* Forces the LLM to respond with valid JSON, useful for structured outputs.
|
|
63
|
+
*
|
|
64
|
+
* @param systemPrompt - The system prompt (should describe the expected JSON format)
|
|
65
|
+
* @param options - Optional configuration
|
|
66
|
+
* @returns An Agent that returns structured JSON responses
|
|
67
|
+
*/
|
|
68
|
+
export function createJsonChatAgent(systemPrompt, options = {}) {
|
|
69
|
+
const { name, description, ...chatOptions } = options;
|
|
70
|
+
return agent$(async (_state, event, ctx) => {
|
|
71
|
+
const messages = [
|
|
72
|
+
{ role: 'system', content: systemPrompt },
|
|
73
|
+
];
|
|
74
|
+
if (event.history) {
|
|
75
|
+
messages.push(...event.history);
|
|
76
|
+
}
|
|
77
|
+
messages.push({ role: 'user', content: event.message });
|
|
78
|
+
// Force JSON mode
|
|
79
|
+
const reply = await ctx.llm.chat(messages, {
|
|
80
|
+
...chatOptions,
|
|
81
|
+
jsonMode: true,
|
|
82
|
+
});
|
|
83
|
+
// Parse the JSON response
|
|
84
|
+
const data = JSON.parse(reply);
|
|
85
|
+
return { data, raw: reply };
|
|
86
|
+
}, {
|
|
87
|
+
name: name || 'json-chat-agent',
|
|
88
|
+
description: description || 'A structured JSON chat agent',
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=basic-chat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"basic-chat.js","sourceRoot":"","sources":["../../src/agents/basic-chat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAuCzC;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,YAAoB,EAAE,UAA4B,EAAE;IAClF,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,GAAG,OAAO,CAAC;IAEtD,OAAO,MAAM,CACX,KAAK,EACH,MAA+B,EAC/B,KAAgB,EAChB,GAAqB,EACA,EAAE;QACvB,0BAA0B;QAC1B,MAAM,QAAQ,GAAsE;YAClF,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE;SAC1C,CAAC;QAEF,uCAAuC;QACvC,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;QAClC,CAAC;QAED,+BAA+B;QAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAExD,sDAAsD;QACtD,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QAExD,OAAO;YACL,KAAK;YACL,QAAQ,EAAE,WAAW,CAAC,QAAQ;YAC9B,KAAK,EAAE,WAAW,CAAC,KAAK;SACzB,CAAC;IACJ,CAAC,EACD;QACE,IAAI,EAAE,IAAI,IAAI,YAAY;QAC1B,WAAW,EAAE,WAAW,IAAI,oBAAoB;KACjD,CACF,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CACjC,YAAoB,EACpB,UAA4B,EAAE;IAE9B,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,GAAG,OAAO,CAAC;IAEtD,OAAO,MAAM,CACX,KAAK,EACH,MAA+B,EAC/B,KAAgB,EAChB,GAAqB,EACc,EAAE;QACrC,MAAM,QAAQ,GAAsE;YAClF,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE;SAC1C,CAAC;QAEF,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;QAClC,CAAC;QAED,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAExD,kBAAkB;QAClB,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE;YACzC,GAAG,WAAW;YACd,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;QAEH,0BAA0B;QAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAM,CAAC;QAEpC,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;IAC9B,CAAC,EACD;QACE,IAAI,EAAE,IAAI,IAAI,iBAAiB;QAC/B,WAAW,EAAE,WAAW,IAAI,8BAA8B;KAC3D,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standard Agent Factories
|
|
3
|
+
*
|
|
4
|
+
* Pre-built agent factories for common use cases.
|
|
5
|
+
*/
|
|
6
|
+
export { createChatAgent, createJsonChatAgent, type ChatInput, type ChatOutput, type ChatAgentOptions, } from './basic-chat.js';
|
|
7
|
+
export { ReActLogic, createReActAgent, availableTools, type ReActInput, type ReActOutput, type ReActStep, type ReActAgentOptions, } from './react.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agents/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,gBAAgB,GACtB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAEL,UAAU,EAEV,gBAAgB,EAEhB,cAAc,EAEd,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,iBAAiB,GACvB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standard Agent Factories
|
|
3
|
+
*
|
|
4
|
+
* Pre-built agent factories for common use cases.
|
|
5
|
+
*/
|
|
6
|
+
export { createChatAgent, createJsonChatAgent, } from './basic-chat.js';
|
|
7
|
+
export {
|
|
8
|
+
// The master logic (compiled agent)
|
|
9
|
+
ReActLogic,
|
|
10
|
+
// The factory (returns VirtualAgent)
|
|
11
|
+
createReActAgent,
|
|
12
|
+
// Available tools list
|
|
13
|
+
availableTools, } from './react.js';
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/agents/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,eAAe,EACf,mBAAmB,GAIpB,MAAM,iBAAiB,CAAC;AAEzB,OAAO;AACL,oCAAoC;AACpC,UAAU;AACV,qCAAqC;AACrC,gBAAgB;AAChB,uBAAuB;AACvB,cAAc,GAMf,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReAct Agent Pattern - Using the "Curried Agent" (VirtualAgent) Pattern
|
|
3
|
+
*
|
|
4
|
+
* Tools are Agents!
|
|
5
|
+
*
|
|
6
|
+
* Custom tools must be wrapped in agent$() so they are:
|
|
7
|
+
* - Durable (the runtime handles retries)
|
|
8
|
+
* - Distributed (can run on different workers)
|
|
9
|
+
* - Serializable (only the hash is passed, not the function)
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { agent$ } from '@alveus-ai/core';
|
|
14
|
+
* import { createReActAgent } from '@alveus-ai/std';
|
|
15
|
+
*
|
|
16
|
+
* // 1. Define custom tool as an Agent
|
|
17
|
+
* const HNTool = agent$(
|
|
18
|
+
* async (state, event) => {
|
|
19
|
+
* const stories = await fetch('https://...').then(r => r.json());
|
|
20
|
+
* return stories.map(s => s.title).join('\n');
|
|
21
|
+
* },
|
|
22
|
+
* { name: 'hn-tool', description: 'Fetches Hacker News stories' }
|
|
23
|
+
* );
|
|
24
|
+
*
|
|
25
|
+
* // 2. Create ReAct agent with custom tools
|
|
26
|
+
* const ResearchAgent = createReActAgent({
|
|
27
|
+
* systemPrompt: 'You are a researcher.',
|
|
28
|
+
* tools: {
|
|
29
|
+
* 'get_news': { agent: HNTool, description: 'Fetches top HN stories' }
|
|
30
|
+
* }
|
|
31
|
+
* });
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
import type { Agent, ExecutionContext, VirtualAgent } from '@alveus-ai/core';
|
|
35
|
+
/**
|
|
36
|
+
* Tool definition for ReAct agents
|
|
37
|
+
*
|
|
38
|
+
* Tools can be:
|
|
39
|
+
* - Built-in (calculator, string) - executed inline
|
|
40
|
+
* - Custom Agents - executed via ctx.call() for durability
|
|
41
|
+
*/
|
|
42
|
+
export interface ToolDefinition {
|
|
43
|
+
/** The tool agent to call (or 'builtin:calculator', 'builtin:string') */
|
|
44
|
+
agent: Agent | string;
|
|
45
|
+
/** Human-readable description for the LLM */
|
|
46
|
+
description: string;
|
|
47
|
+
/** JSON Schema for parameters (as string for LLM prompt) */
|
|
48
|
+
parameters?: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Input schema for the ReAct Logic
|
|
52
|
+
*/
|
|
53
|
+
export interface ReActInput {
|
|
54
|
+
/** System prompt defining the agent's behavior */
|
|
55
|
+
systemPrompt: string;
|
|
56
|
+
/**
|
|
57
|
+
* Tools available to the agent
|
|
58
|
+
*
|
|
59
|
+
* Map of tool name -> tool config (hash + description)
|
|
60
|
+
* The hash is used to call the tool agent via ctx.call()
|
|
61
|
+
*/
|
|
62
|
+
tools: Record<string, {
|
|
63
|
+
/** Agent hash (or 'builtin:calculator', 'builtin:string') */
|
|
64
|
+
hash: string;
|
|
65
|
+
/** Description for the LLM */
|
|
66
|
+
description: string;
|
|
67
|
+
/** Parameter schema for the LLM */
|
|
68
|
+
parameters?: string;
|
|
69
|
+
}>;
|
|
70
|
+
/** The user's query/input */
|
|
71
|
+
input: string;
|
|
72
|
+
/** Optional context for the query */
|
|
73
|
+
context?: string;
|
|
74
|
+
/** Maximum iterations (default: 10) */
|
|
75
|
+
maxIterations?: number;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* A single step in the ReAct execution trace
|
|
79
|
+
*/
|
|
80
|
+
export interface ReActStep {
|
|
81
|
+
type: 'thought' | 'action' | 'observation';
|
|
82
|
+
content: string;
|
|
83
|
+
tool?: string;
|
|
84
|
+
params?: Record<string, any>;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Output from ReAct agents
|
|
88
|
+
*/
|
|
89
|
+
export interface ReActOutput {
|
|
90
|
+
answer: string;
|
|
91
|
+
steps: ReActStep[];
|
|
92
|
+
iterations: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The ReAct Logic - Compiled and frozen ONCE at build time
|
|
96
|
+
*
|
|
97
|
+
* This is the "master brain" that gets reused for all ReAct agents.
|
|
98
|
+
* Configuration (systemPrompt, tools) comes from the event input.
|
|
99
|
+
*
|
|
100
|
+
* Tools are called via ctx.call() for durability,
|
|
101
|
+
* except for built-in tools which are executed inline.
|
|
102
|
+
*/
|
|
103
|
+
export declare const ReActLogic: Agent<{}, ReActInput, ExecutionContext, any>;
|
|
104
|
+
/**
|
|
105
|
+
* Options for creating a ReAct agent
|
|
106
|
+
*/
|
|
107
|
+
export interface ReActAgentOptions {
|
|
108
|
+
/** System prompt defining the agent's behavior */
|
|
109
|
+
systemPrompt: string;
|
|
110
|
+
/**
|
|
111
|
+
* Tools available to this agent
|
|
112
|
+
*
|
|
113
|
+
* Can be:
|
|
114
|
+
* - Built-in tool names: 'calculator', 'string'
|
|
115
|
+
* - Custom tool agents: { agent: MyToolAgent, description: '...' }
|
|
116
|
+
*/
|
|
117
|
+
tools?: Record<string, ToolDefinition | string>;
|
|
118
|
+
/** Maximum iterations before giving up (default: 10) */
|
|
119
|
+
maxIterations?: number;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Create a ReAct agent with the given configuration
|
|
123
|
+
*
|
|
124
|
+
* This returns a VirtualAgent that points to the pre-compiled ReActLogic
|
|
125
|
+
* with pre-filled configuration. No new code is generated.
|
|
126
|
+
*
|
|
127
|
+
* @param options - Agent configuration
|
|
128
|
+
* @returns A VirtualAgent ready for execution
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```ts
|
|
132
|
+
* // With built-in tools only
|
|
133
|
+
* const mathAgent = createReActAgent({
|
|
134
|
+
* systemPrompt: 'You are a math assistant.',
|
|
135
|
+
* tools: { calculator: 'calculator', string: 'string' }
|
|
136
|
+
* });
|
|
137
|
+
*
|
|
138
|
+
* // With custom tool agents
|
|
139
|
+
* const researchAgent = createReActAgent({
|
|
140
|
+
* systemPrompt: 'You are a researcher.',
|
|
141
|
+
* tools: {
|
|
142
|
+
* calculator: 'calculator', // built-in
|
|
143
|
+
* get_news: { agent: HNToolAgent, description: 'Fetches HN stories' }
|
|
144
|
+
* }
|
|
145
|
+
* });
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
export declare function createReActAgent(options: ReActAgentOptions): VirtualAgent<ReActInput>;
|
|
149
|
+
/**
|
|
150
|
+
* List of available built-in tools
|
|
151
|
+
*/
|
|
152
|
+
export declare const availableTools: string[];
|
|
153
|
+
//# sourceMappingURL=react.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../src/agents/react.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE7E;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,yEAAyE;IACzE,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC;IAEtB,6CAA6C;IAC7C,WAAW,EAAE,MAAM,CAAC;IAEpB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,kDAAkD;IAClD,YAAY,EAAE,MAAM,CAAC;IAErB;;;;;OAKG;IACH,KAAK,EAAE,MAAM,CACX,MAAM,EACN;QACE,6DAA6D;QAC7D,IAAI,EAAE,MAAM,CAAC;QACb,8BAA8B;QAC9B,WAAW,EAAE,MAAM,CAAC;QACpB,mCAAmC;QACnC,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CACF,CAAC;IAEF,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAC;IAEd,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,uCAAuC;IACvC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,SAAS,GAAG,QAAQ,GAAG,aAAa,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,8CAqNtB,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,kDAAkD;IAClD,YAAY,EAAE,MAAM,CAAC;IAErB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAAC,CAAC;IAEhD,wDAAwD;IACxD,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAkBD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,YAAY,CAAC,UAAU,CAAC,CAoCrF;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,UAA6B,CAAC"}
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReAct Agent Pattern - Using the "Curried Agent" (VirtualAgent) Pattern
|
|
3
|
+
*
|
|
4
|
+
* Tools are Agents!
|
|
5
|
+
*
|
|
6
|
+
* Custom tools must be wrapped in agent$() so they are:
|
|
7
|
+
* - Durable (the runtime handles retries)
|
|
8
|
+
* - Distributed (can run on different workers)
|
|
9
|
+
* - Serializable (only the hash is passed, not the function)
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { agent$ } from '@alveus-ai/core';
|
|
14
|
+
* import { createReActAgent } from '@alveus-ai/std';
|
|
15
|
+
*
|
|
16
|
+
* // 1. Define custom tool as an Agent
|
|
17
|
+
* const HNTool = agent$(
|
|
18
|
+
* async (state, event) => {
|
|
19
|
+
* const stories = await fetch('https://...').then(r => r.json());
|
|
20
|
+
* return stories.map(s => s.title).join('\n');
|
|
21
|
+
* },
|
|
22
|
+
* { name: 'hn-tool', description: 'Fetches Hacker News stories' }
|
|
23
|
+
* );
|
|
24
|
+
*
|
|
25
|
+
* // 2. Create ReAct agent with custom tools
|
|
26
|
+
* const ResearchAgent = createReActAgent({
|
|
27
|
+
* systemPrompt: 'You are a researcher.',
|
|
28
|
+
* tools: {
|
|
29
|
+
* 'get_news': { agent: HNTool, description: 'Fetches top HN stories' }
|
|
30
|
+
* }
|
|
31
|
+
* });
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
import { agent$ } from '@alveus-ai/core';
|
|
35
|
+
/**
|
|
36
|
+
* The ReAct Logic - Compiled and frozen ONCE at build time
|
|
37
|
+
*
|
|
38
|
+
* This is the "master brain" that gets reused for all ReAct agents.
|
|
39
|
+
* Configuration (systemPrompt, tools) comes from the event input.
|
|
40
|
+
*
|
|
41
|
+
* Tools are called via ctx.call() for durability,
|
|
42
|
+
* except for built-in tools which are executed inline.
|
|
43
|
+
*/
|
|
44
|
+
export const ReActLogic = agent$(async (_state, event, ctx) => {
|
|
45
|
+
// ===== BUILT-IN TOOL EXECUTORS =====
|
|
46
|
+
// These run inline (not as separate agents) for simplicity
|
|
47
|
+
const BUILTIN_EXECUTORS = {
|
|
48
|
+
'builtin:calculator': async ({ expression }) => {
|
|
49
|
+
const sanitized = String(expression).replace(/[^0-9+\-*/().%\s]/g, '');
|
|
50
|
+
if (sanitized !== String(expression)) {
|
|
51
|
+
throw new Error('Invalid characters in expression');
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
const result = new Function(`return ${sanitized}`)();
|
|
55
|
+
return String(result);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
throw new Error(`Failed to evaluate: ${expression}`);
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
'builtin:string': async ({ operation, text }) => {
|
|
62
|
+
switch (operation) {
|
|
63
|
+
case 'length':
|
|
64
|
+
return String(text.length);
|
|
65
|
+
case 'uppercase':
|
|
66
|
+
return text.toUpperCase();
|
|
67
|
+
case 'lowercase':
|
|
68
|
+
return text.toLowerCase();
|
|
69
|
+
case 'reverse':
|
|
70
|
+
return text.split('').reverse().join('');
|
|
71
|
+
default:
|
|
72
|
+
throw new Error(`Unknown operation: ${operation}`);
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
// ===== BUILD SYSTEM PROMPT =====
|
|
77
|
+
const buildPrompt = (basePrompt, tools) => {
|
|
78
|
+
const toolDescriptions = Object.entries(tools)
|
|
79
|
+
.map(([name, tool]) => {
|
|
80
|
+
const params = tool.parameters || '{ ... }';
|
|
81
|
+
return `- ${name}: ${tool.description}\n Parameters: ${params}`;
|
|
82
|
+
})
|
|
83
|
+
.join('\n');
|
|
84
|
+
return `${basePrompt}
|
|
85
|
+
|
|
86
|
+
Available tools:
|
|
87
|
+
${toolDescriptions}
|
|
88
|
+
|
|
89
|
+
You MUST respond with a JSON object in this exact format:
|
|
90
|
+
{
|
|
91
|
+
"thought": "Your reasoning about what to do next",
|
|
92
|
+
"action": { "tool": "tool_name", "params": { ... } } OR null if you have the final answer,
|
|
93
|
+
"answer": "Your final answer to the user" OR null if you need to use a tool
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
Rules:
|
|
97
|
+
1. Always start with a thought explaining your reasoning
|
|
98
|
+
2. If you need information or need to calculate something, use a tool by setting "action"
|
|
99
|
+
3. When you have enough information, set "answer" and leave "action" null
|
|
100
|
+
4. Use exactly one tool per response
|
|
101
|
+
5. Never make up information - use tools to get facts`;
|
|
102
|
+
};
|
|
103
|
+
const buildMsgs = (sysPrompt, userInput, steps) => {
|
|
104
|
+
const messages = [
|
|
105
|
+
{ role: 'system', content: sysPrompt },
|
|
106
|
+
{ role: 'user', content: userInput },
|
|
107
|
+
];
|
|
108
|
+
for (const step of steps) {
|
|
109
|
+
if (step.type === 'thought') {
|
|
110
|
+
messages.push({
|
|
111
|
+
role: 'assistant',
|
|
112
|
+
content: JSON.stringify({
|
|
113
|
+
thought: step.content,
|
|
114
|
+
action: step.tool ? { tool: step.tool, params: step.params } : null,
|
|
115
|
+
answer: null,
|
|
116
|
+
}),
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
else if (step.type === 'observation') {
|
|
120
|
+
messages.push({
|
|
121
|
+
role: 'user',
|
|
122
|
+
content: `Tool result: ${step.content}`,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return messages;
|
|
127
|
+
};
|
|
128
|
+
// ===== EXECUTE TOOL =====
|
|
129
|
+
const executeTool = async (toolName, hash, params) => {
|
|
130
|
+
// Check if it's a built-in tool
|
|
131
|
+
if (hash.startsWith('builtin:')) {
|
|
132
|
+
const executor = BUILTIN_EXECUTORS[hash];
|
|
133
|
+
if (!executor) {
|
|
134
|
+
throw new Error(`Unknown built-in tool: ${hash}`);
|
|
135
|
+
}
|
|
136
|
+
return await executor(params);
|
|
137
|
+
}
|
|
138
|
+
// It's a custom tool agent - call via ctx.call() for durability!
|
|
139
|
+
ctx.logger.info(`Calling tool agent: ${toolName}`, { hash: hash.slice(0, 16), params });
|
|
140
|
+
const result = await ctx.call(hash, params);
|
|
141
|
+
// Tool agents should return a string or something stringifiable
|
|
142
|
+
return typeof result === 'string' ? result : JSON.stringify(result);
|
|
143
|
+
};
|
|
144
|
+
// ===== MAIN REACT LOOP =====
|
|
145
|
+
const { systemPrompt, tools, input, context, maxIterations = 10 } = event;
|
|
146
|
+
const steps = [];
|
|
147
|
+
let iterations = 0;
|
|
148
|
+
const fullPrompt = buildPrompt(systemPrompt, tools);
|
|
149
|
+
const fullInput = context ? `Context: ${context}\n\nQuestion: ${input}` : input;
|
|
150
|
+
ctx.logger.info('Starting ReAct loop', { maxIterations, toolCount: Object.keys(tools).length });
|
|
151
|
+
while (iterations < maxIterations) {
|
|
152
|
+
iterations++;
|
|
153
|
+
const messages = buildMsgs(fullPrompt, fullInput, steps);
|
|
154
|
+
// Get LLM response with JSON mode
|
|
155
|
+
const responseText = await ctx.llm.chat(messages, { jsonMode: true });
|
|
156
|
+
// Parse response
|
|
157
|
+
let response;
|
|
158
|
+
try {
|
|
159
|
+
response = JSON.parse(responseText);
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
steps.push({
|
|
163
|
+
type: 'observation',
|
|
164
|
+
content: 'Error: Invalid JSON response. Please respond with valid JSON.',
|
|
165
|
+
});
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
// Record thought
|
|
169
|
+
if (response.thought) {
|
|
170
|
+
ctx.logger.info(`Thought: ${response.thought.slice(0, 100)}...`);
|
|
171
|
+
steps.push({ type: 'thought', content: response.thought });
|
|
172
|
+
}
|
|
173
|
+
// Check for final answer
|
|
174
|
+
if (response.answer && !response.action) {
|
|
175
|
+
ctx.logger.info('ReAct completed with answer', { iterations });
|
|
176
|
+
return { answer: response.answer, steps, iterations };
|
|
177
|
+
}
|
|
178
|
+
// Execute action
|
|
179
|
+
if (response.action) {
|
|
180
|
+
const toolName = response.action.tool;
|
|
181
|
+
const toolDef = tools[toolName];
|
|
182
|
+
if (!toolDef) {
|
|
183
|
+
steps.push({
|
|
184
|
+
type: 'action',
|
|
185
|
+
content: `Attempted unknown tool: ${toolName}`,
|
|
186
|
+
tool: toolName,
|
|
187
|
+
params: response.action.params,
|
|
188
|
+
});
|
|
189
|
+
steps.push({
|
|
190
|
+
type: 'observation',
|
|
191
|
+
content: `Error: Tool "${toolName}" not available. Available tools: ${Object.keys(tools).join(', ')}`,
|
|
192
|
+
});
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
steps.push({
|
|
196
|
+
type: 'action',
|
|
197
|
+
content: `Using ${toolName}`,
|
|
198
|
+
tool: toolName,
|
|
199
|
+
params: response.action.params,
|
|
200
|
+
});
|
|
201
|
+
try {
|
|
202
|
+
const result = await executeTool(toolName, toolDef.hash, response.action.params);
|
|
203
|
+
steps.push({ type: 'observation', content: result });
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
steps.push({
|
|
207
|
+
type: 'observation',
|
|
208
|
+
content: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
ctx.logger.warn('ReAct hit max iterations', { maxIterations });
|
|
214
|
+
return {
|
|
215
|
+
answer: `Unable to complete within ${maxIterations} iterations.`,
|
|
216
|
+
steps,
|
|
217
|
+
iterations,
|
|
218
|
+
};
|
|
219
|
+
}, { name: 'ReActLogic', version: '2.0.0' });
|
|
220
|
+
/**
|
|
221
|
+
* Built-in tool definitions
|
|
222
|
+
*/
|
|
223
|
+
const BUILTIN_TOOLS = {
|
|
224
|
+
calculator: {
|
|
225
|
+
hash: 'builtin:calculator',
|
|
226
|
+
description: 'Performs arithmetic calculations. Supports +, -, *, /, and parentheses.',
|
|
227
|
+
parameters: '{ expression: string }',
|
|
228
|
+
},
|
|
229
|
+
string: {
|
|
230
|
+
hash: 'builtin:string',
|
|
231
|
+
description: 'Performs string operations: length, uppercase, lowercase, reverse',
|
|
232
|
+
parameters: '{ operation: "length" | "uppercase" | "lowercase" | "reverse", text: string }',
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
/**
|
|
236
|
+
* Create a ReAct agent with the given configuration
|
|
237
|
+
*
|
|
238
|
+
* This returns a VirtualAgent that points to the pre-compiled ReActLogic
|
|
239
|
+
* with pre-filled configuration. No new code is generated.
|
|
240
|
+
*
|
|
241
|
+
* @param options - Agent configuration
|
|
242
|
+
* @returns A VirtualAgent ready for execution
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```ts
|
|
246
|
+
* // With built-in tools only
|
|
247
|
+
* const mathAgent = createReActAgent({
|
|
248
|
+
* systemPrompt: 'You are a math assistant.',
|
|
249
|
+
* tools: { calculator: 'calculator', string: 'string' }
|
|
250
|
+
* });
|
|
251
|
+
*
|
|
252
|
+
* // With custom tool agents
|
|
253
|
+
* const researchAgent = createReActAgent({
|
|
254
|
+
* systemPrompt: 'You are a researcher.',
|
|
255
|
+
* tools: {
|
|
256
|
+
* calculator: 'calculator', // built-in
|
|
257
|
+
* get_news: { agent: HNToolAgent, description: 'Fetches HN stories' }
|
|
258
|
+
* }
|
|
259
|
+
* });
|
|
260
|
+
* ```
|
|
261
|
+
*/
|
|
262
|
+
export function createReActAgent(options) {
|
|
263
|
+
// Convert tool definitions to the format expected by ReActInput
|
|
264
|
+
const tools = {};
|
|
265
|
+
const inputTools = options.tools ?? { calculator: 'calculator', string: 'string' };
|
|
266
|
+
for (const [name, def] of Object.entries(inputTools)) {
|
|
267
|
+
if (typeof def === 'string') {
|
|
268
|
+
// Built-in tool by name
|
|
269
|
+
const builtin = BUILTIN_TOOLS[def];
|
|
270
|
+
if (!builtin) {
|
|
271
|
+
throw new Error(`Unknown built-in tool: ${def}. Available: ${Object.keys(BUILTIN_TOOLS).join(', ')}`);
|
|
272
|
+
}
|
|
273
|
+
tools[name] = builtin;
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
// Custom tool agent
|
|
277
|
+
const agentHash = typeof def.agent === 'string' ? def.agent : def.agent.definition.hash;
|
|
278
|
+
tools[name] = {
|
|
279
|
+
hash: agentHash,
|
|
280
|
+
description: def.description,
|
|
281
|
+
parameters: def.parameters,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return {
|
|
286
|
+
definition: ReActLogic,
|
|
287
|
+
defaultInput: {
|
|
288
|
+
systemPrompt: options.systemPrompt,
|
|
289
|
+
tools,
|
|
290
|
+
maxIterations: options.maxIterations ?? 10,
|
|
291
|
+
},
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* List of available built-in tools
|
|
296
|
+
*/
|
|
297
|
+
export const availableTools = Object.keys(BUILTIN_TOOLS);
|
|
298
|
+
//# sourceMappingURL=react.js.map
|