@antseed/ant-agent 0.1.14
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/LICENSE +674 -0
- package/README.md +212 -0
- package/dist/agent-loop.d.ts +27 -0
- package/dist/agent-loop.d.ts.map +1 -0
- package/dist/agent-loop.js +278 -0
- package/dist/agent-loop.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/loader.d.ts +38 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +77 -0
- package/dist/loader.js.map +1 -0
- package/dist/provider.d.ts +24 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +81 -0
- package/dist/provider.js.map +1 -0
- package/dist/sse-parser.d.ts +10 -0
- package/dist/sse-parser.d.ts.map +1 -0
- package/dist/sse-parser.js +294 -0
- package/dist/sse-parser.js.map +1 -0
- package/dist/system-prompt.d.ts +16 -0
- package/dist/system-prompt.d.ts.map +1 -0
- package/dist/system-prompt.js +94 -0
- package/dist/system-prompt.js.map +1 -0
- package/dist/tools.d.ts +66 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +260 -0
- package/dist/tools.js.map +1 -0
- package/package.json +25 -0
package/README.md
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# @antseed/ant-agent
|
|
2
|
+
|
|
3
|
+
Ant agent runtime for AntSeed. Lets seed runners monetize their knowledge by wrapping any provider with a persona, guardrails, on-demand knowledge modules, and custom tools.
|
|
4
|
+
|
|
5
|
+
An ant agent is a **read-only, knowledge-augmented AI service**. It doesn't act on the user's behalf — it answers questions using curated expertise that the creator packages and maintains.
|
|
6
|
+
|
|
7
|
+
## How it works
|
|
8
|
+
|
|
9
|
+
1. Creator defines an agent: persona + guardrails + knowledge modules (markdown files)
|
|
10
|
+
2. On each buyer request, persona, guardrails, and an `antseed_load_knowledge` tool are injected
|
|
11
|
+
3. The LLM decides when to load knowledge — it calls the tool with a module name and receives the content
|
|
12
|
+
4. The agent loop executes internal tool calls and re-prompts until the LLM produces a final text response
|
|
13
|
+
5. The buyer gets a clean streamed response — no internal tools or loop artifacts
|
|
14
|
+
|
|
15
|
+
When no knowledge modules are defined, no tools are injected and it's a single-call injection (persona + guardrails only).
|
|
16
|
+
|
|
17
|
+
## Agent directory structure
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
my-agent/
|
|
21
|
+
agent.json # manifest
|
|
22
|
+
persona.md # who the agent is
|
|
23
|
+
knowledge/ # knowledge modules
|
|
24
|
+
linkedin-posting.md
|
|
25
|
+
content-strategy.md
|
|
26
|
+
tools/ # custom tool scripts (optional)
|
|
27
|
+
fetch-trends.js
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### agent.json
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"name": "social-media-advisor",
|
|
35
|
+
"persona": "./persona.md",
|
|
36
|
+
"guardrails": [
|
|
37
|
+
"Never write posts without explicit request",
|
|
38
|
+
"Always disclose AI-generated content when asked"
|
|
39
|
+
],
|
|
40
|
+
"knowledge": [
|
|
41
|
+
{
|
|
42
|
+
"name": "linkedin-posting",
|
|
43
|
+
"description": "Creating and optimizing LinkedIn posts",
|
|
44
|
+
"file": "./knowledge/linkedin-posting.md"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"name": "content-strategy",
|
|
48
|
+
"description": "Content calendars and strategy frameworks",
|
|
49
|
+
"file": "./knowledge/content-strategy.md"
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
"tools": [
|
|
53
|
+
{
|
|
54
|
+
"name": "fetch_trends",
|
|
55
|
+
"description": "Fetch trending topics for a platform",
|
|
56
|
+
"parameters": {
|
|
57
|
+
"type": "object",
|
|
58
|
+
"properties": { "platform": { "type": "string" } },
|
|
59
|
+
"required": ["platform"]
|
|
60
|
+
},
|
|
61
|
+
"execute": "./tools/fetch-trends.js"
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
| Field | Required | Description |
|
|
68
|
+
|---|---|---|
|
|
69
|
+
| `name` | Yes | Agent name |
|
|
70
|
+
| `persona` | No | Path to markdown file with the agent's system prompt / personality |
|
|
71
|
+
| `guardrails` | No | Array of hard rules the agent must follow |
|
|
72
|
+
| `knowledge` | No | Array of knowledge modules for on-demand loading |
|
|
73
|
+
| `knowledge[].name` | Yes | Unique identifier for the module |
|
|
74
|
+
| `knowledge[].description` | Yes | Short description — shown to the LLM to decide relevance |
|
|
75
|
+
| `knowledge[].file` | Yes | Path to the markdown file with the full content |
|
|
76
|
+
| `tools` | No | Array of custom tools the LLM can call |
|
|
77
|
+
| `tools[].name` | Yes | Tool name (auto-prefixed with `antseed_`) |
|
|
78
|
+
| `tools[].description` | Yes | Description shown to the LLM |
|
|
79
|
+
| `tools[].parameters` | No | JSON Schema for tool parameters (defaults to empty object) |
|
|
80
|
+
| `tools[].execute` | Yes | Path to a JS file that exports a default function |
|
|
81
|
+
| `confidentialityPrompt` | No | Custom confidentiality instruction (has a sensible default) |
|
|
82
|
+
|
|
83
|
+
## Usage
|
|
84
|
+
|
|
85
|
+
### Programmatic
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import { loadAntAgent, AntAgentProvider } from '@antseed/ant-agent';
|
|
89
|
+
|
|
90
|
+
// Load agent (knowledge + tools from agent.json)
|
|
91
|
+
const agent = await loadAntAgent('./my-agent');
|
|
92
|
+
const boundProvider = new AntAgentProvider(innerProvider, agent);
|
|
93
|
+
|
|
94
|
+
// Per-service agents
|
|
95
|
+
const socialAgent = await loadAntAgent('./social-agent');
|
|
96
|
+
const codingAgent = await loadAntAgent('./coding-agent');
|
|
97
|
+
const boundProvider = new AntAgentProvider(innerProvider, {
|
|
98
|
+
'social-model-v1': socialAgent,
|
|
99
|
+
'coding-model-v1': codingAgent,
|
|
100
|
+
'*': socialAgent,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
node.registerProvider(boundProvider);
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### CLI
|
|
107
|
+
|
|
108
|
+
Add `agentDir` to your antseed config. Use a string for a single agent (all services), or a map for per-service agents:
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"seller": {
|
|
113
|
+
"agentDir": "./my-agent"
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Per-service:
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"seller": {
|
|
123
|
+
"agentDir": {
|
|
124
|
+
"social-model-v1": "./agents/social",
|
|
125
|
+
"coding-model-v1": "./agents/coding",
|
|
126
|
+
"*": "./agents/default"
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The `"*"` key is a fallback for services with no explicit agent. Services with no matching agent pass through unchanged.
|
|
133
|
+
|
|
134
|
+
Then run `antseed seed` as usual.
|
|
135
|
+
|
|
136
|
+
## Knowledge loading
|
|
137
|
+
|
|
138
|
+
When knowledge modules are defined, the `antseed_load_knowledge` tool is injected into the request alongside any buyer tools. The tool description includes a catalog of available module names and descriptions.
|
|
139
|
+
|
|
140
|
+
The LLM decides which modules to load based on the conversation. It can:
|
|
141
|
+
|
|
142
|
+
- Load one module, get the content, then respond
|
|
143
|
+
- Load multiple modules across successive tool calls
|
|
144
|
+
- Respond directly without loading any modules if the question doesn't require specialized knowledge
|
|
145
|
+
|
|
146
|
+
This keeps the context focused — only the knowledge the LLM judges relevant gets loaded. A buyer asking about LinkedIn won't get X/Twitter knowledge bloating the context.
|
|
147
|
+
|
|
148
|
+
## Custom tools
|
|
149
|
+
|
|
150
|
+
Beyond knowledge loading, creators can add custom tools that the LLM can call during the agent loop. Define tools in `agent.json` with an `execute` field pointing to a JS file:
|
|
151
|
+
|
|
152
|
+
```json
|
|
153
|
+
{
|
|
154
|
+
"tools": [{
|
|
155
|
+
"name": "fetch_trends",
|
|
156
|
+
"description": "Fetch trending topics for a platform",
|
|
157
|
+
"parameters": {
|
|
158
|
+
"type": "object",
|
|
159
|
+
"properties": { "platform": { "type": "string" } },
|
|
160
|
+
"required": ["platform"]
|
|
161
|
+
},
|
|
162
|
+
"execute": "./tools/fetch-trends.js"
|
|
163
|
+
}]
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
The JS file exports a default function that receives the tool arguments and returns a string:
|
|
168
|
+
|
|
169
|
+
```js
|
|
170
|
+
// tools/fetch-trends.js
|
|
171
|
+
export default async function(args) {
|
|
172
|
+
const res = await fetch(`https://api.example.com/trends/${args.platform}`);
|
|
173
|
+
return await res.text();
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Tool names are automatically prefixed with `antseed_` when injected (e.g., `fetch_trends` becomes `antseed_fetch_trends`). The LLM sees all internal tools alongside buyer tools, with system prompt instructions to use `antseed_*` tools for context gathering and buyer tools only as requested.
|
|
178
|
+
|
|
179
|
+
If a tool's execute function throws, the error message is returned to the LLM as an error result so it can recover gracefully.
|
|
180
|
+
|
|
181
|
+
### Programmatic tools
|
|
182
|
+
|
|
183
|
+
Tools can also be added programmatically via the options parameter (useful when tools need access to runtime state):
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
import { AntAgentProvider, loadAntAgent, type AntAgentTool } from '@antseed/ant-agent';
|
|
187
|
+
|
|
188
|
+
const customTool: AntAgentTool = {
|
|
189
|
+
name: 'lookup_user',
|
|
190
|
+
description: 'Look up user details',
|
|
191
|
+
parameters: { type: 'object', properties: { id: { type: 'string' } }, required: ['id'] },
|
|
192
|
+
execute: async (args) => db.users.findById(args.id),
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
const agent = await loadAntAgent('./my-agent');
|
|
196
|
+
new AntAgentProvider(innerProvider, agent, { tools: [customTool] });
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Manifest tools and programmatic tools are merged together.
|
|
200
|
+
|
|
201
|
+
## What gets injected
|
|
202
|
+
|
|
203
|
+
The system prompt is assembled in this order:
|
|
204
|
+
|
|
205
|
+
1. **Persona** — the agent's identity and expertise
|
|
206
|
+
2. **Tool-set instructions** — tells the LLM how to use `antseed_` tools vs buyer tools (only when knowledge modules exist)
|
|
207
|
+
3. **Guardrails** — hard rules
|
|
208
|
+
4. **Confidentiality prompt** — prevents the LLM from revealing injected content
|
|
209
|
+
|
|
210
|
+
Additionally, `antseed_*` tools are added to the request's tool list alongside any buyer-provided tools. This includes the built-in `antseed_load_knowledge` (when knowledge modules are defined) and any custom tools passed via options.
|
|
211
|
+
|
|
212
|
+
The buyer's own system prompt (if any) is preserved after the agent's content.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Provider, SerializedHttpRequest, SerializedHttpResponse, ProviderStreamCallbacks } from '@antseed/node';
|
|
2
|
+
import type { AntAgentDefinition } from './loader.js';
|
|
3
|
+
import type { AntAgentTool } from './tools.js';
|
|
4
|
+
export interface AgentLoopOptions {
|
|
5
|
+
/** Maximum tool-call rounds before forcing a final request. Total LLM calls = maxIterations + 1. Default: 5. */
|
|
6
|
+
maxIterations?: number;
|
|
7
|
+
/** Additional tools available to the agent loop. Auto-prefixed with `antseed_`. */
|
|
8
|
+
tools?: AntAgentTool[];
|
|
9
|
+
}
|
|
10
|
+
/** Agent definition paired with its pre-built tool list. Created once at construction. */
|
|
11
|
+
export interface ResolvedAgent {
|
|
12
|
+
definition: AntAgentDefinition;
|
|
13
|
+
tools: AntAgentTool[];
|
|
14
|
+
}
|
|
15
|
+
export type AgentResolver = (body: Record<string, unknown>) => ResolvedAgent | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Non-streaming agent loop. Runs tool iterations buffered, returns final response.
|
|
18
|
+
*/
|
|
19
|
+
export declare function runAgentLoop(inner: Provider, req: SerializedHttpRequest, resolve: AgentResolver, options?: AgentLoopOptions): Promise<SerializedHttpResponse>;
|
|
20
|
+
/**
|
|
21
|
+
* Streaming agent loop. Every LLM call streams to the buyer in real time.
|
|
22
|
+
* Tool calls are intercepted at the end of each stream, executed, and the
|
|
23
|
+
* next iteration streams again — so the buyer sees tokens arriving live
|
|
24
|
+
* throughout the entire conversation.
|
|
25
|
+
*/
|
|
26
|
+
export declare function runAgentLoopStream(inner: Provider, req: SerializedHttpRequest, resolve: AgentResolver, callbacks: ProviderStreamCallbacks, options?: AgentLoopOptions): Promise<SerializedHttpResponse>;
|
|
27
|
+
//# sourceMappingURL=agent-loop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-loop.d.ts","sourceRoot":"","sources":["../src/agent-loop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EACR,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,EACxB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAoB/C,MAAM,WAAW,gBAAgB;IAC/B,gHAAgH;IAChH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mFAAmF;IACnF,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC;CACxB;AAED,0FAA0F;AAC1F,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,kBAAkB,CAAC;IAC/B,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,aAAa,GAAG,SAAS,CAAC;AAwFzF;;GAEG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,QAAQ,EACf,GAAG,EAAE,qBAAqB,EAC1B,OAAO,EAAE,aAAa,EACtB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,sBAAsB,CAAC,CAuDjC;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,QAAQ,EACf,GAAG,EAAE,qBAAqB,EAC1B,OAAO,EAAE,aAAa,EACtB,SAAS,EAAE,uBAAuB,EAClC,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,sBAAsB,CAAC,CAoIjC"}
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import { detectRequestFormat, isToolChoiceForced, injectTools, inspectResponse, executeTools, appendToolLoop, stripInternalToolCalls, } from './tools.js';
|
|
2
|
+
import { buildSystemPrompt, injectSystemPrompt } from './system-prompt.js';
|
|
3
|
+
import { parseSSEResponse } from './sse-parser.js';
|
|
4
|
+
import { TOOL_PREFIX } from './tools.js';
|
|
5
|
+
const encoder = new TextEncoder();
|
|
6
|
+
const decoder = new TextDecoder();
|
|
7
|
+
const DEFAULT_MAX_ITERATIONS = 5;
|
|
8
|
+
function normalizeDebugValue(value) {
|
|
9
|
+
return (value ?? '').trim().toLowerCase();
|
|
10
|
+
}
|
|
11
|
+
function isDebugEnabled() {
|
|
12
|
+
const fromAntseed = normalizeDebugValue(process.env['ANTSEED_DEBUG']);
|
|
13
|
+
if (['1', 'true', 'yes', 'on'].includes(fromAntseed))
|
|
14
|
+
return true;
|
|
15
|
+
return normalizeDebugValue(process.env['DEBUG'])
|
|
16
|
+
.split(',')
|
|
17
|
+
.some((ns) => {
|
|
18
|
+
const trimmed = ns.trim();
|
|
19
|
+
return trimmed === '*' || trimmed === 'antseed' || trimmed === 'antseed:*';
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
const DEBUG_ENABLED = isDebugEnabled();
|
|
23
|
+
function debugLog(...args) {
|
|
24
|
+
if (DEBUG_ENABLED)
|
|
25
|
+
console.log(...args);
|
|
26
|
+
}
|
|
27
|
+
/** Check if an SSE chunk contains an Anthropic message_start event. */
|
|
28
|
+
function chunkHasMessageStart(data) {
|
|
29
|
+
const text = decoder.decode(data);
|
|
30
|
+
return text.includes('event: message_start') || text.includes('"type":"message_start"') || text.includes('"type": "message_start"');
|
|
31
|
+
}
|
|
32
|
+
/** Check if an SSE chunk contains a Responses API response.created event. */
|
|
33
|
+
function chunkHasResponseCreated(data) {
|
|
34
|
+
const text = decoder.decode(data);
|
|
35
|
+
return text.includes('event: response.created');
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Check if an SSE chunk contains an internal (antseed_*) tool call.
|
|
39
|
+
* Used during streaming to decide whether to forward chunks to the buyer.
|
|
40
|
+
*/
|
|
41
|
+
function chunkHasInternalToolCall(data, format) {
|
|
42
|
+
const text = decoder.decode(data);
|
|
43
|
+
if (format === 'openai') {
|
|
44
|
+
// OpenAI: look for "name":"antseed_" in tool_calls deltas
|
|
45
|
+
for (const line of text.split('\n')) {
|
|
46
|
+
if (!line.startsWith('data: ') || line === 'data: [DONE]')
|
|
47
|
+
continue;
|
|
48
|
+
try {
|
|
49
|
+
const chunk = JSON.parse(line.slice(6).trimEnd());
|
|
50
|
+
const choices = chunk.choices;
|
|
51
|
+
const toolCalls = choices?.[0]?.delta?.tool_calls;
|
|
52
|
+
if (toolCalls?.some(tc => tc.function?.name?.startsWith(TOOL_PREFIX)))
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
catch { /* ignore */ }
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
// Anthropic & Responses API: look for antseed_ name in content blocks or output items
|
|
60
|
+
if (text.includes(`"name":"${TOOL_PREFIX}`) || text.includes(`"name": "${TOOL_PREFIX}`))
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
/** Prepare the request body: parse, resolve agent, inject system prompt + tools. */
|
|
66
|
+
function prepareBody(req, resolve) {
|
|
67
|
+
let body;
|
|
68
|
+
try {
|
|
69
|
+
body = JSON.parse(decoder.decode(req.body));
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
const agent = resolve(body);
|
|
75
|
+
if (!agent)
|
|
76
|
+
return null;
|
|
77
|
+
const { definition, tools } = agent;
|
|
78
|
+
const willInjectTools = tools.length > 0 && !isToolChoiceForced(body);
|
|
79
|
+
const reqTag = `[AntAgent] ${req.method} ${req.path} (reqId=${req.requestId.slice(0, 8)})`;
|
|
80
|
+
debugLog(`${reqTag}: resolved agent "${definition.name}" with ${tools.length} tool(s): ${tools.map(t => t.name).join(', ') || 'none'}${willInjectTools ? '' : ' (tools skipped)'}`);
|
|
81
|
+
const systemPrompt = buildSystemPrompt(definition, willInjectTools);
|
|
82
|
+
body = injectSystemPrompt(body, systemPrompt, detectRequestFormat(req.path));
|
|
83
|
+
body = injectTools(body, tools, detectRequestFormat(req.path));
|
|
84
|
+
return { body, agent, reqTag };
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Non-streaming agent loop. Runs tool iterations buffered, returns final response.
|
|
88
|
+
*/
|
|
89
|
+
export async function runAgentLoop(inner, req, resolve, options) {
|
|
90
|
+
const prepared = prepareBody(req, resolve);
|
|
91
|
+
if (!prepared)
|
|
92
|
+
return inner.handleRequest(req);
|
|
93
|
+
const { agent, reqTag } = prepared;
|
|
94
|
+
let { body } = prepared;
|
|
95
|
+
const format = detectRequestFormat(req.path);
|
|
96
|
+
const maxIterations = options?.maxIterations ?? DEFAULT_MAX_ITERATIONS;
|
|
97
|
+
// Force non-streaming for the buffered loop
|
|
98
|
+
delete body.stream;
|
|
99
|
+
for (let i = 0; i < maxIterations; i++) {
|
|
100
|
+
debugLog(`${reqTag}: loop iteration ${i + 1}/${maxIterations}`);
|
|
101
|
+
const augReq = {
|
|
102
|
+
...req,
|
|
103
|
+
body: encoder.encode(JSON.stringify(body)),
|
|
104
|
+
};
|
|
105
|
+
const response = await inner.handleRequest(augReq);
|
|
106
|
+
let responseBody;
|
|
107
|
+
try {
|
|
108
|
+
responseBody = JSON.parse(decoder.decode(response.body));
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return response;
|
|
112
|
+
}
|
|
113
|
+
const action = inspectResponse(responseBody, format);
|
|
114
|
+
if (action.type === 'done') {
|
|
115
|
+
const cleaned = stripInternalToolCalls(responseBody, format);
|
|
116
|
+
return { ...response, body: encoder.encode(JSON.stringify(cleaned)) };
|
|
117
|
+
}
|
|
118
|
+
debugLog(`${reqTag}: executing ${action.internalCalls.length} tool(s): ${action.internalCalls.map(c => c.name).join(', ')}`);
|
|
119
|
+
const results = await executeTools(action.internalCalls, agent.tools);
|
|
120
|
+
debugLog(`${reqTag}: tool results: ${results.map(r => `${r.id}:${r.isError ? 'error' : 'ok'}`).join(', ')}`);
|
|
121
|
+
body = appendToolLoop(body, responseBody, results, format);
|
|
122
|
+
}
|
|
123
|
+
// Max iterations — one final call
|
|
124
|
+
debugLog(`${reqTag}: max iterations (${maxIterations}) reached`);
|
|
125
|
+
const finalReq = {
|
|
126
|
+
...req,
|
|
127
|
+
body: encoder.encode(JSON.stringify(body)),
|
|
128
|
+
};
|
|
129
|
+
const response = await inner.handleRequest(finalReq);
|
|
130
|
+
try {
|
|
131
|
+
const responseBody = JSON.parse(decoder.decode(response.body));
|
|
132
|
+
const cleaned = stripInternalToolCalls(responseBody, format);
|
|
133
|
+
return { ...response, body: encoder.encode(JSON.stringify(cleaned)) };
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
return response;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Streaming agent loop. Every LLM call streams to the buyer in real time.
|
|
141
|
+
* Tool calls are intercepted at the end of each stream, executed, and the
|
|
142
|
+
* next iteration streams again — so the buyer sees tokens arriving live
|
|
143
|
+
* throughout the entire conversation.
|
|
144
|
+
*/
|
|
145
|
+
export async function runAgentLoopStream(inner, req, resolve, callbacks, options) {
|
|
146
|
+
const prepared = prepareBody(req, resolve);
|
|
147
|
+
if (!prepared)
|
|
148
|
+
return inner.handleRequestStream(req, callbacks);
|
|
149
|
+
const { agent, reqTag } = prepared;
|
|
150
|
+
let { body } = prepared;
|
|
151
|
+
const format = detectRequestFormat(req.path);
|
|
152
|
+
const maxIterations = options?.maxIterations ?? DEFAULT_MAX_ITERATIONS;
|
|
153
|
+
let headersSent = false;
|
|
154
|
+
let messageStartSent = false;
|
|
155
|
+
for (let i = 0; i < maxIterations; i++) {
|
|
156
|
+
debugLog(`${reqTag}: stream iteration ${i + 1}/${maxIterations}`);
|
|
157
|
+
const isLastAllowedIteration = i === maxIterations - 1;
|
|
158
|
+
const augReq = {
|
|
159
|
+
...req,
|
|
160
|
+
body: encoder.encode(JSON.stringify({ ...body, stream: true })),
|
|
161
|
+
};
|
|
162
|
+
// Stream the call, forwarding chunks to the buyer.
|
|
163
|
+
// For Anthropic format: suppress message_start on non-first iterations and
|
|
164
|
+
// message_stop on non-final iterations to maintain one continuous SSE envelope.
|
|
165
|
+
// For both formats: suppress antseed_* tool call chunks.
|
|
166
|
+
let streamResponse;
|
|
167
|
+
let suppressingChunks = false;
|
|
168
|
+
try {
|
|
169
|
+
streamResponse = await inner.handleRequestStream(augReq, {
|
|
170
|
+
onResponseStart: (res) => {
|
|
171
|
+
if (!headersSent) {
|
|
172
|
+
callbacks.onResponseStart(res);
|
|
173
|
+
headersSent = true;
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
onResponseChunk: (chunk) => {
|
|
177
|
+
if (suppressingChunks)
|
|
178
|
+
return;
|
|
179
|
+
if (!chunk.done && chunk.data.length > 0) {
|
|
180
|
+
// Check if this chunk reveals an internal tool call
|
|
181
|
+
if (chunkHasInternalToolCall(chunk.data, format)) {
|
|
182
|
+
suppressingChunks = true;
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
if (format === 'anthropic' && chunkHasMessageStart(chunk.data)) {
|
|
186
|
+
// Suppress message_start if we already sent one (one continuous envelope)
|
|
187
|
+
if (messageStartSent)
|
|
188
|
+
return;
|
|
189
|
+
messageStartSent = true;
|
|
190
|
+
}
|
|
191
|
+
if (format === 'openai-responses' && chunkHasResponseCreated(chunk.data)) {
|
|
192
|
+
if (messageStartSent)
|
|
193
|
+
return;
|
|
194
|
+
messageStartSent = true;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
callbacks.onResponseChunk(chunk);
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
// If streaming fails, try non-streaming fallback with tool call stripping
|
|
203
|
+
debugLog(`${reqTag}: stream failed, falling back to non-streaming`);
|
|
204
|
+
const augReqNonStream = {
|
|
205
|
+
...req,
|
|
206
|
+
body: encoder.encode(JSON.stringify({ ...body, stream: false })),
|
|
207
|
+
};
|
|
208
|
+
const response = await inner.handleRequest(augReqNonStream);
|
|
209
|
+
let responseBody = response.body;
|
|
210
|
+
try {
|
|
211
|
+
const parsed = JSON.parse(decoder.decode(response.body));
|
|
212
|
+
const cleaned = stripInternalToolCalls(parsed, format);
|
|
213
|
+
responseBody = encoder.encode(JSON.stringify(cleaned));
|
|
214
|
+
}
|
|
215
|
+
catch { /* non-JSON — use as-is */ }
|
|
216
|
+
const cleanedResponse = { ...response, body: responseBody };
|
|
217
|
+
if (!headersSent) {
|
|
218
|
+
callbacks.onResponseStart(cleanedResponse);
|
|
219
|
+
headersSent = true;
|
|
220
|
+
}
|
|
221
|
+
callbacks.onResponseChunk({ requestId: req.requestId, data: responseBody, done: true });
|
|
222
|
+
return cleanedResponse;
|
|
223
|
+
}
|
|
224
|
+
// Parse the buffered SSE response to check for tool calls
|
|
225
|
+
let responseBody;
|
|
226
|
+
try {
|
|
227
|
+
responseBody = parseSSEResponse(streamResponse.body, format);
|
|
228
|
+
}
|
|
229
|
+
catch {
|
|
230
|
+
// Can't parse — treat as done
|
|
231
|
+
return streamResponse;
|
|
232
|
+
}
|
|
233
|
+
const action = inspectResponse(responseBody, format);
|
|
234
|
+
if (action.type === 'done') {
|
|
235
|
+
if (suppressingChunks) {
|
|
236
|
+
// We suppressed chunks (detected internal tool call) but inspectResponse
|
|
237
|
+
// resolved as done (e.g. mixed buyer+internal calls). Close the buyer's stream.
|
|
238
|
+
callbacks.onResponseChunk({ requestId: req.requestId, data: new Uint8Array(0), done: true });
|
|
239
|
+
}
|
|
240
|
+
debugLog(`${reqTag}: stream iteration ${i + 1} done (no internal tool calls)`);
|
|
241
|
+
return streamResponse;
|
|
242
|
+
}
|
|
243
|
+
// Internal tool calls found — execute them
|
|
244
|
+
debugLog(`${reqTag}: stream iteration ${i + 1} — executing ${action.internalCalls.length} tool(s): ${action.internalCalls.map(c => c.name).join(', ')}`);
|
|
245
|
+
const results = await executeTools(action.internalCalls, agent.tools);
|
|
246
|
+
debugLog(`${reqTag}: stream iteration ${i + 1} — tool results: ${results.map(r => `${r.id}:${r.isError ? 'error' : 'ok'}`).join(', ')}`);
|
|
247
|
+
body = appendToolLoop(body, responseBody, results, format);
|
|
248
|
+
// If this was the last allowed iteration, break to make a final streaming call
|
|
249
|
+
if (isLastAllowedIteration) {
|
|
250
|
+
debugLog(`${reqTag}: max iterations (${maxIterations}) reached, making final streaming call`);
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// Final streaming call after max iterations (or maxIterations=0)
|
|
255
|
+
const finalReq = {
|
|
256
|
+
...req,
|
|
257
|
+
body: encoder.encode(JSON.stringify({ ...body, stream: true })),
|
|
258
|
+
};
|
|
259
|
+
return inner.handleRequestStream(finalReq, {
|
|
260
|
+
onResponseStart: (res) => {
|
|
261
|
+
if (!headersSent) {
|
|
262
|
+
callbacks.onResponseStart(res);
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
onResponseChunk: (chunk) => {
|
|
266
|
+
if (!chunk.done && chunk.data.length > 0) {
|
|
267
|
+
// Anthropic: suppress message_start if we already sent one (continuing the envelope)
|
|
268
|
+
if (format === 'anthropic' && messageStartSent && chunkHasMessageStart(chunk.data))
|
|
269
|
+
return;
|
|
270
|
+
// Responses API: suppress response.created if we already sent one
|
|
271
|
+
if (format === 'openai-responses' && messageStartSent && chunkHasResponseCreated(chunk.data))
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
callbacks.onResponseChunk(chunk);
|
|
275
|
+
},
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
//# sourceMappingURL=agent-loop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-loop.js","sourceRoot":"","sources":["../src/agent-loop.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { AntAgentProvider } from './provider.js';
|
|
2
|
+
export { loadAntAgent, type AntAgentDefinition, type KnowledgeModule } from './loader.js';
|
|
3
|
+
export { type AgentLoopOptions } from './agent-loop.js';
|
|
4
|
+
export { type AntAgentTool, knowledgeTool } from './tools.js';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAC1F,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,KAAK,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,YAAY,EAAiD,MAAM,aAAa,CAAC;AAE1F,OAAO,EAAqB,aAAa,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/loader.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { AntAgentTool } from './tools.js';
|
|
2
|
+
export interface KnowledgeModule {
|
|
3
|
+
/** Unique name for this knowledge module. */
|
|
4
|
+
name: string;
|
|
5
|
+
/** Short description shown to the LLM during knowledge selection. */
|
|
6
|
+
description: string;
|
|
7
|
+
/** Full markdown content loaded from file. */
|
|
8
|
+
content: string;
|
|
9
|
+
}
|
|
10
|
+
export interface AntAgentDefinition {
|
|
11
|
+
/** Agent name. */
|
|
12
|
+
name: string;
|
|
13
|
+
/** Persona / system prompt content (loaded from markdown file). */
|
|
14
|
+
persona: string;
|
|
15
|
+
/** Hard rules the agent must follow. */
|
|
16
|
+
guardrails: string[];
|
|
17
|
+
/** Knowledge modules available for selective loading. */
|
|
18
|
+
knowledge: KnowledgeModule[];
|
|
19
|
+
/** Tools loaded from the manifest (execute files dynamically imported). */
|
|
20
|
+
tools?: AntAgentTool[];
|
|
21
|
+
/** Custom confidentiality prompt. Uses a built-in default when omitted. */
|
|
22
|
+
confidentialityPrompt?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Load an ant agent definition from a directory containing `agent.json`.
|
|
26
|
+
*
|
|
27
|
+
* The directory structure:
|
|
28
|
+
* ```
|
|
29
|
+
* my-agent/
|
|
30
|
+
* agent.json # manifest
|
|
31
|
+
* persona.md # persona / system prompt
|
|
32
|
+
* knowledge/ # knowledge modules (markdown files)
|
|
33
|
+
* topic-a.md
|
|
34
|
+
* topic-b.md
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare function loadAntAgent(agentDir: string): Promise<AntAgentDefinition>;
|
|
38
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,WAAW,eAAe;IAC9B,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,WAAW,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,kBAAkB;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,yDAAyD;IACzD,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,2EAA2E;IAC3E,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC;IACvB,2EAA2E;IAC3E,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AA8BD;;;;;;;;;;;;GAYG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAgEhF"}
|