@atgs/tapeworm 0.1.7 → 0.1.9

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.
@@ -1,20 +1,81 @@
1
+ /**
2
+ * The Agent module contains all things related to Agents, including:
3
+ * - the Agent class
4
+ * - the AgentBuilder class
5
+ * - the default callback handler for an Agent.
6
+ *
7
+ * This module contains most of the business logic for running the main agent loop.
8
+ *
9
+ * @module
10
+ */
1
11
  import Conversation, { ConversationManager } from "../conversation/conversation";
2
12
  import Message from "../conversation/message";
3
13
  import { type Model } from "../model/model";
4
14
  import type Tool from "../tool/tool";
5
15
  import type ToolCall from "../tool/toolCall";
6
16
  /**
7
- * Coordinates a model, its tools, and the running conversation to fulfill user queries.
17
+ * Agents combine a model with your tools.
18
+ *
19
+ * To build an agent, use the AgentBuilder class:
20
+ *
21
+ * ```ts
22
+ * const agent = Agent.builder()
23
+ * .name("yourAgent")
24
+ * .tools([new YourTool()])
25
+ * .systemPrompt("You are an agent.")
26
+ * .model(yourModel)
27
+ * .build();
28
+ * ```
29
+ *
8
30
  */
9
31
  export default class Agent {
32
+ /**
33
+ * The name of the agent.
34
+ */
10
35
  name: string;
36
+ /**
37
+ * The system prompt (if any) for the agent.
38
+ */
11
39
  systemPrompt?: string;
40
+ /**
41
+ * The tools this agent knows about and can run.
42
+ */
12
43
  tools: Tool[];
44
+ /**
45
+ * The underlying model for the agent.
46
+ */
13
47
  model: Model;
48
+ /**
49
+ * The conversation for the agent.
50
+ * You do not normally need to set this parameter unless you are building a use case
51
+ * where you have a persistent session with an agent.
52
+ */
14
53
  conversation: Conversation;
54
+ /**
55
+ * The conversation manager for the agent.
56
+ * Normally, a converstation manager that does nothing will be used.
57
+ * When SummarizingConversationManager or RAGConversationManager is implemented, these will help you avoid
58
+ * token overflow.
59
+ */
15
60
  conversationManager?: ConversationManager;
16
- toolNameToIndexMap: any | undefined;
61
+ /**
62
+ * A cache for looking up tools in the Tools array.
63
+ * DO NOT MANUALLY SET THIS VALUE. AGENT AUTOMATICALLY TAKES CARE OF IT.
64
+ */
65
+ private toolNameToIndexMap;
66
+ /**
67
+ * The callback function, invoked for every response from the model.
68
+ * The default implementation just prints to std.out or your console.
69
+ */
17
70
  callback: (m: Message) => void;
71
+ /**
72
+ * This is the constructor for an Agent.
73
+ *
74
+ * i IMPLORE YOU not to use this method. You CAN, but you should be using the Builder instead
75
+ * for the best results, as this method WILL change with future updates.
76
+ *
77
+ * Builder will be a lot more stable and will always be backwards compatible.
78
+ */
18
79
  constructor(name: string, tools: Tool[], model: Model, conversationManager: ConversationManager, callback: (m: Message) => void);
19
80
  /**
20
81
  * Run the full agent loop for a user query: seed the conversation, invoke the model,
@@ -39,9 +100,12 @@ export default class Agent {
39
100
  * Build a lookup from tool name to index for efficient resolution of tool calls.
40
101
  */
41
102
  generateToolNameToIndexMap(): void;
103
+ /**
104
+ * Get a builder to build an Agent.
105
+ */
42
106
  static builder(): AgentBuilder;
43
107
  }
44
- declare class AgentBuilder {
108
+ export declare class AgentBuilder {
45
109
  _name: string;
46
110
  _systemPrompt?: string;
47
111
  _tools: Tool[];
@@ -50,14 +114,45 @@ declare class AgentBuilder {
50
114
  _conversationManager: ConversationManager;
51
115
  _toolNameToIndexMap: any | undefined;
52
116
  _callback: (m: Message) => void;
117
+ /**
118
+ * Set the name of the agent.
119
+ */
53
120
  name(name: string): AgentBuilder;
121
+ /**
122
+ * Set the system prompt of the agent.
123
+ */
54
124
  systemPrompt(systemPrompt: string | undefined): AgentBuilder;
125
+ /**
126
+ * Set the tools of the agent, if you already have an array of tools.
127
+ */
55
128
  tools(tools: Tool[]): AgentBuilder;
129
+ /**
130
+ * Add a tool, 1 by 1, to the agent..
131
+ */
56
132
  addTool(tool: Tool): AgentBuilder;
133
+ /**
134
+ * Set the underlying model for the agent.
135
+ */
57
136
  model(model: Model): AgentBuilder;
137
+ /**
138
+ * Set the conversation manager for the agent.
139
+ */
58
140
  conversationManager(mgr: ConversationManager): AgentBuilder;
141
+ /**
142
+ * Set the callback for the agent.
143
+ */
59
144
  callback(callback: (m: Message) => void): AgentBuilder;
145
+ /**
146
+ * Build the agent.
147
+ */
60
148
  build(): Agent;
61
149
  }
150
+ /**
151
+ * This function is Tapeworm's default callback function.
152
+ * If you do not specify your own callback function, then this will be called and all
153
+ * it will do is log output to the screen.
154
+ *
155
+ * You can override this per invocation or on the Agent itself to do other things
156
+ * with the LLM output.
157
+ */
62
158
  export declare function defaultCallback(m: Message): void;
63
- export {};
@@ -1,7 +1,20 @@
1
+ /**
2
+ * The Conversation module contains the Conversation class and the ConversationManager prototypes.
3
+ *
4
+ * The Conversation is a wrapper around both a manager and an array of messages.
5
+ *
6
+ * The Conversation Manager is an object that can perform operations on only the conversation.
7
+ *
8
+ * While no Conversation Managers have been implemented yet, they will allow resilience to overflowing context windows.
9
+ *
10
+ * @module
11
+ */
1
12
  import type { Message } from "..";
2
13
  import type { Model } from "../model/model";
3
14
  /**
4
- * Maintains ordered chat messages and delegates to a conversation manager for compaction.
15
+ * A Conversation holds an array of messages and its associated manager.
16
+ *
17
+ * Conversations are (mostly) immutable, until the manager steps in and compacts the conversation.
5
18
  */
6
19
  export default class Conversation {
7
20
  messages: Message[];
@@ -17,7 +30,7 @@ export default class Conversation {
17
30
  append(message: Message): void;
18
31
  }
19
32
  /**
20
- * Strategy interface for pruning or transforming a conversation history.
33
+ * Interface for compacting a Conversation. Future implementations can summarize or do RAG-based compaction
21
34
  */
22
35
  export declare class ConversationManager {
23
36
  /**
@@ -1,3 +1,15 @@
1
+ /**
2
+ * The Messages module contains all the shapes that make up a single Message.
3
+ * - The actual Message class, which is a role + an array of MessageComponents
4
+ * - And a builder, too, which you should use 99.999% of the time!
5
+ * - An enum called MessageComponentType
6
+ * - The MessageComponents
7
+ * - **Content** - normal text from the LLM
8
+ * - **Thinking** - chain-of-thought reasoning from the LLM
9
+ * - **ToolCall** is not technically contained here, but it is a message component type
10
+ * - **ToolResult** - encodes the result of a tool call.
11
+ * @module
12
+ */
1
13
  import type ToolCall from "../tool/toolCall";
2
14
  /**
3
15
  * Messages are the units of a Conversation
package/dist/index.d.ts CHANGED
@@ -1,3 +1,10 @@
1
+ /**
2
+ * The index module gathers the exports from Tapeworm.
3
+ *
4
+ * This file should be modified when new classes are introduced to Tapeworm
5
+ *
6
+ * @module
7
+ */
1
8
  export { default as Agent } from "./agent/agent";
2
9
  export { default as Conversation, ConversationManager, DefaultConversationManager, } from "./conversation/conversation";
3
10
  export { Model, ModelRequest, ModelRequestBuilder } from "./model/model";
@@ -1,8 +1,18 @@
1
+ /**
2
+ * Tapeworm's first mostly-working model is OllamaModel,
3
+ * which routes model requests to an Ollama endpoint on your local machine.
4
+ *
5
+ * Other Models will be housed in separate NPM packages to allow better portability
6
+ * and to leverage the existing NPM packages (for example, the AWS SDK in the case of Bedrock)
7
+ * for those models.
8
+ *
9
+ * @module
10
+ */
1
11
  import { Message } from "..";
2
12
  import ToolCall from "../tool/toolCall";
3
13
  import { Model, ModelRequest } from "./model";
4
14
  /**
5
- * Model adapter that translates between Tapeworm message/tool shapes and the Ollama chat API.
15
+ * The Ollama Model class. This translates between Tapeworm message/tool shapes and the Ollama chat API.
6
16
  */
7
17
  export default class OllamaModel extends Model {
8
18
  endpoint: string;
@@ -1,3 +1,13 @@
1
+ /**
2
+ * The Model module lays out the interface for a Tapeworm model.
3
+ *
4
+ * It contains the base Model class, which doesn't do anything other than throw errors and specify an interface,
5
+ * and also the ModelRequest and ModelRequestBuilder classes, which show what kind of shape a model expects to
6
+ * recieve upon invocation.
7
+ *
8
+ *
9
+ * @module
10
+ */
1
11
  import type Message from "../conversation/message";
2
12
  import type Tool from "../tool/tool";
3
13
  /**
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class w{messages;manager;constructor(){this.messages=[],this.manager=new g}append(e){this.messages.push(e),this.messages=this.manager.compact(this.messages)}}class M{compact(e){throw new y("No implementation for conversation manager!")}configure(e){throw new y("No implementation for conversation manager!")}}class g extends M{compact(e){return e}configure(e){}}class y extends Error{constructor(e){super(e),this.name="ConversationManagerNotImplemented"}}class u{role;content;constructor(e,s){this.role=e,this.content=s}static builder(){return new b}filter(e){return this.content.filter(s=>s.getMessageComponentType()==e)}}class b{_role;_content;role(e){return this._role=e,this}init(){this._content==null&&(this._content=[])}toolCall(e){return e==null?this:(this.init(),this._content.push(e),this)}toolCalls(e){if(e==null)return this;this.init();for(const s of e)this._content.push(s);return this}toolResult(e){return e==null?this:(this.init(),this._content.push(e),this)}thinking(e){return e==null?this:(this.init(),this._content.push(C.of(e)),this)}content(e){return e==null?this:(this.init(),this._content.push(N.of(e)),this)}build(){if(this._content==null||this._content.length==0)throw new Error("Role-only messages are not supported by Tapeworm.");return new u(this._role,this._content)}}const l={Content:"content",Thinking:"thinking",ToolCall:"toolcall",ToolResult:"toolresult"};class m{getMessageComponentType(){throw new Error("Message components that do not have a message component type are not allowed.")}}class N extends m{text;constructor(e){super(),this.text=e}getMessageComponentType(){return l.Content}get(){return this.text}static of(e){return new this(e)}}class C extends m{thought;constructor(e){super(),this.thought=e}getMessageComponentType(){return l.Thinking}get(){return this.thought}static of(e){return new this(e)}}class c extends m{id;toolName;toolResult;constructor(e,s,o){super(),this.id=e,this.toolName=s,this.toolResult=o}getMessageComponentType(){return l.ToolResult}static of(e,s){return new this(e.id,e.name,s)}}class P{async invoke(e){throw new v("The invoke function for this model was not correctly implemented.")}tokenLimit(){throw new v("The tokenLimit function for this model was not correctly implemented.")}}class q{messages;tools;constructor(e,s){this.messages=e,this.tools=s}static builder(){return new f}}class f{_messages;_tools;messages(e){return this._messages=e,this}tools(e){return this._tools=e,this}build(){if(this._tools==null&&(this._tools=[]),this._messages==null)throw new j("Requests to the model should include content.");return new q(this._messages,this._tools)}}class v extends Error{constructor(e){super(e),this.name="ModelNotImplementedError"}}class j extends Error{constructor(e){super(e),this.name="MessagesNotDefinedError"}}class _ extends m{sequence;name;parameters;type;id;getMessageComponentType(){return l.ToolCall}constructor(e,s,o,n,r){super(),this.sequence=e,this.name=s,this.parameters=o,this.type=n,this.id=r}static builder(){return new x}}class x{_sequence;_name;_parameters;_type;_id;sequence(e){return this._sequence=e,this}name(e){return this._name=e,this}parameters(e){return this._parameters=e,this}type(e){return this._type=e,this}id(e){return e!=null&&(this._id=e),this}build(){return this._sequence==null&&(this._sequence=0),this._id==null&&(this._id=(Math.random()+1).toString(36).slice(2,7)),new _(this._sequence,this._name,this._parameters,this._type,this._id)}}class D extends Error{constructor(e){super(e),this.name="ToolNotFoundError"}}class k{name;systemPrompt;tools;model;conversation;conversationManager;toolNameToIndexMap;callback;constructor(e,s,o,n,r){this.name=e,this.model=o,this.conversationManager=n,this.tools=s,this.callback=r,this.conversationManager.configure(o)}async invoke(e,s=this.callback){this.conversation==null&&(this.conversation=new w,this.conversationManager!=null&&(this.conversation.manager=this.conversationManager),this.systemPrompt!=null&&this.conversation.append(u.builder().role("system").content(this.systemPrompt).build())),this.conversation.append(u.builder().role("user").content(e).build());let o=!1;for(;!o;){let n=await this._runQuery();s(n),this.conversation.append(n),o=!0;const r=n.filter(l.ToolCall);if(r!=null&&r.length!=0){o=!1,r.sort((a,i)=>(a.sequence??0)<(i.sequence??0)?-1:1);for(let a of r)await this._runTool(a)}}}async _runQuery(){return await this.model.invoke(new f().messages(this.conversation?.messages).tools(this.tools).build())}async _runTool(e){if(this.generateToolNameToIndexMap(),!(e.name in this.toolNameToIndexMap)){this.conversation.append(u.builder().role("tool").toolResult(c.of(e,new D("Agent does not have a tool with this name."))).build());return}let s=this.tools[this.toolNameToIndexMap[e.name]];try{let o=await s.execute(e.parameters);this.conversation.append(u.builder().role("tool").toolResult(c.of(e,o)).build())}catch(o){this.conversation.append(u.builder().role("tool").toolResult(c.of(e,JSON.stringify(o))).build())}}generateToolNameToIndexMap(){if(this.toolNameToIndexMap==null){this.toolNameToIndexMap={};for(let e=0;e<this.tools.length;e++)this.toolNameToIndexMap[this.tools[e].getName()]=e}}static builder(){return new A}}class A{_name;_systemPrompt;_tools;_model;_conversation;_conversationManager=new g;_toolNameToIndexMap;_callback=e=>J(e);name(e){return this._name=e,this}systemPrompt(e){return this._systemPrompt=e,this}tools(e){return this._tools=e,this}addTool(e){return this._tools==null&&(this._tools=[]),this._tools.push(e),this}model(e){return this._model=e,this}conversationManager(e){return this._conversationManager=e,this}callback(e){return this._callback=e,this}build(){let e=new k(this._name,this._tools,this._model,this._conversationManager,this._callback);return this._conversation!=null&&(e.conversation=this._conversation),this._systemPrompt!=null&&(e.systemPrompt=this._systemPrompt),e}}function J(t){for(const e of t.filter(l.Thinking))console.log("\x1B[90m"+e.get()+"\x1B[0m");for(const e of t.filter(l.Content))console.log(e.get());for(const e of t.filter(l.ToolCall))console.log("\x1B[32mCalling Tool: "+e.name+"\x1B[0m")}class d extends Error{constructor(e){super(e),this.name="ToolNotDefinedError"}}class F{name;description;tool_schema;constructor(){this.name=this.getName(),this.description=this.getDescription(),this.tool_schema=this.getToolSchema()}getName(){throw new d("Tool name not defined.")}getDescription(){throw new d("Tool description not defined.")}getToolSchema(){throw new d("Tool parameter schema not defined.")}execute(e){return null}}class p{parameters;output;constructor(e,s){this.parameters=e,this.output=s}static builder(){return new O}}class O{_parameters;_output;addParameter(e){return this._parameters==null&&(this._parameters=[]),this._parameters.push(e),this}output(e){return this._output=e,this}build(){return this._parameters==null&&(this._parameters=[]),new p(this._parameters,this._output)}}class T{name;description;type;required;constructor(e,s,o,n){this.name=e,this.description=s,this.type=o,this.required=n,this.assertValidType()}assertValidType(){}static builder(){return new S}}class S{_name;_description;_type;_required;name(e){return this._name=e,this}description(e){return this._description=e,this}type(e){return this._type=e,this}required(e){return this._required=e,this}build(){return this._required==null&&(this._required=!1),new T(this._name,this._description,this._type,this._required)}}class L extends P{endpoint;model;options;constructor(e,s,o){super(),this.endpoint=e,this.model=s,this.options=o}async invoke(e){let s={model:this.model,messages:this._formatMessages(e),tools:this._formatTools(e),...this.options},o=await fetch(this.endpoint+"/api/chat",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!o.ok)throw new Error(`HTTP error! status: ${o.status}`);let n=await o.json(),r=[];if(n.message.tool_calls)for(let a in n.message.tool_calls){const i=n.message.tool_calls[a];let h="function",R=i[h]?.name,E=i[h]?.index,B=i.id??void 0,I=typeof i[h]?.arguments=="string"?JSON.parse(i[h]?.arguments):i[h]?.arguments;r.push(_.builder().name(R).type(h).parameters(I).sequence(E).id(B).build())}return u.builder().toolCalls(r).role(n.message.role).content(n.message.content).thinking(n.message.thinking).build()}_formatTools(e){let s=[];for(let o of e.tools){let n={},r=[];for(let i of o.getToolSchema().parameters)n[i.name]={},n[i.name].type=i.type,n[i.name].description=i.description,i.required&&r.push(i.name);let a={type:"function",function:{name:o.getName(),description:o.getDescription(),parameters:{type:"object",properties:n,required:r}}};s.push(a)}return s}_formatMessages(e){let s=[];for(let o of e.messages){if(o.role=="assistant"||o.role=="system"||o.role=="user"){s.push(this._formatSingleMessage(o));continue}if(o.role=="tool"){for(const n of o.content)if(n.getMessageComponentType()==l.ToolResult){const r=n;s.push({role:o.role,name:r.toolName,content:JSON.stringify(r.toolResult)})}}}return s}_formatSingleMessage(e){let s={role:e.role},o,n,r;for(const a of e.content){if(a.getMessageComponentType()==l.Content){const i=a;o==null&&(o=""),o+=i.get()}if(a.getMessageComponentType()==l.Thinking){const i=a;r==null&&(r=""),r+=i.get()}if(a.getMessageComponentType()==l.ToolCall){const i=a;n==null&&(n=[]),n.push(this._formatToolCall(i))}}return o!=null&&(s.content=o),n!=null&&(s.tool_calls=n),r!=null&&(s.thinking=r),s}_formatToolCall(e){return{function:{name:e.name,arguments:e.parameters}}}}function Q(t){return e=>{e.prototype.getName=()=>t}}function V(t){return e=>{Object.defineProperty(e.prototype,"getDescription",{value:function(){return t},enumerable:!0,configurable:!0,writable:!0})}}function H(t){return e=>{e.prototype.tapewormParams==null&&(e.prototype.tapewormParams=[]),e.prototype.tapewormParamsOutput==null&&(e.prototype.tapewormParamsOutput=""),e.prototype.tapewormParams.push(T.builder().name(t.name).description(t.description).required(t.required).type(t.type).build()),e.prototype.getToolSchema=()=>new p(e.prototype.tapewormParams,e.prototype.tapewormParamsOutput)}}function K(t){return e=>{e.prototype.tapewormParams==null&&(e.prototype.tapewormParams=[]),e.prototype.tapewormParamsOutput==null&&(e.prototype.tapewormParamsOutput=""),e.prototype.tapewormParamsOutput=t,e.prototype.getToolSchema=()=>new p(e.prototype.tapewormParams,e.prototype.tapewormParamsOutput)}}exports.Agent=k;exports.Content=N;exports.Conversation=w;exports.ConversationManager=M;exports.DefaultConversationManager=g;exports.Message=u;exports.MessageBuilder=b;exports.MessageComponent=m;exports.MessageComponentType=l;exports.Model=P;exports.ModelRequest=q;exports.ModelRequestBuilder=f;exports.OllamaModel=L;exports.Parameter=T;exports.ParameterBuilder=S;exports.Thinking=C;exports.Tool=F;exports.ToolCall=_;exports.ToolCallBuilder=x;exports.ToolDescription=V;exports.ToolName=Q;exports.ToolOutput=K;exports.ToolParameter=H;exports.ToolResult=c;exports.ToolSchema=p;exports.ToolSchemaBuilder=O;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class w{messages;manager;constructor(){this.messages=[],this.manager=new g}append(e){this.messages.push(e),this.messages=this.manager.compact(this.messages)}}class M{compact(e){throw new T("No implementation for conversation manager!")}configure(e){throw new T("No implementation for conversation manager!")}}class g extends M{compact(e){return e}configure(e){}}class T extends Error{constructor(e){super(e),this.name="ConversationManagerNotImplemented"}}class u{role;content;constructor(e,s){this.role=e,this.content=s}static builder(){return new b}filter(e){return this.content.filter(s=>s.getMessageComponentType()==e)}}class b{_role;_content;role(e){return this._role=e,this}init(){this._content==null&&(this._content=[])}toolCall(e){return e==null?this:(this.init(),this._content.push(e),this)}toolCalls(e){if(e==null)return this;this.init();for(const s of e)this._content.push(s);return this}toolResult(e){return e==null?this:(this.init(),this._content.push(e),this)}thinking(e){return e==null?this:(this.init(),this._content.push(N.of(e)),this)}content(e){return e==null?this:(this.init(),this._content.push(C.of(e)),this)}build(){if(this._content==null||this._content.length==0)throw new Error("Role-only messages are not supported by Tapeworm.");return new u(this._role,this._content)}}const l={Content:"content",Thinking:"thinking",ToolCall:"toolcall",ToolResult:"toolresult"};class m{getMessageComponentType(){throw new Error("Message components that do not have a message component type are not allowed.")}}class C extends m{text;constructor(e){super(),this.text=e}getMessageComponentType(){return l.Content}get(){return this.text}static of(e){return new this(e)}}class N extends m{thought;constructor(e){super(),this.thought=e}getMessageComponentType(){return l.Thinking}get(){return this.thought}static of(e){return new this(e)}}class c extends m{id;toolName;toolResult;constructor(e,s,o){super(),this.id=e,this.toolName=s,this.toolResult=o}getMessageComponentType(){return l.ToolResult}static of(e,s){return new this(e.id,e.name,s)}}class P{async invoke(e){throw new v("The invoke function for this model was not correctly implemented.")}tokenLimit(){throw new v("The tokenLimit function for this model was not correctly implemented.")}}class q{messages;tools;constructor(e,s){this.messages=e,this.tools=s}static builder(){return new f}}class f{_messages;_tools;messages(e){return this._messages=e,this}tools(e){return this._tools=e,this}build(){if(this._tools==null&&(this._tools=[]),this._messages==null)throw new j("Requests to the model should include content.");return new q(this._messages,this._tools)}}class v extends Error{constructor(e){super(e),this.name="ModelNotImplementedError"}}class j extends Error{constructor(e){super(e),this.name="MessagesNotDefinedError"}}class _ extends m{sequence;name;parameters;type;id;getMessageComponentType(){return l.ToolCall}constructor(e,s,o,r,n){super(),this.sequence=e,this.name=s,this.parameters=o,this.type=r,this.id=n}static builder(){return new x}}class x{_sequence;_name;_parameters;_type;_id;sequence(e){return this._sequence=e,this}name(e){return this._name=e,this}parameters(e){return this._parameters=e,this}type(e){return this._type=e,this}id(e){return e!=null&&(this._id=e),this}build(){return this._sequence==null&&(this._sequence=0),this._id==null&&(this._id=(Math.random()+1).toString(36).slice(2,7)),new _(this._sequence,this._name,this._parameters,this._type,this._id)}}class D extends Error{constructor(e){super(e),this.name="ToolNotFoundError"}}class k{name;systemPrompt;tools;model;conversation;conversationManager;toolNameToIndexMap;callback;constructor(e,s,o,r,n){this.name=e,this.model=o,this.conversationManager=r,this.tools=s,this.callback=n,this.conversationManager.configure(o)}async invoke(e,s=this.callback){this.conversation==null&&(this.conversation=new w,this.conversationManager!=null&&(this.conversation.manager=this.conversationManager),this.systemPrompt!=null&&this.conversation.append(u.builder().role("system").content(this.systemPrompt).build())),this.conversation.append(u.builder().role("user").content(e).build());let o=!1;for(;!o;){let r=await this._runQuery();s(r),this.conversation.append(r),o=!0;const n=r.filter(l.ToolCall);if(n!=null&&n.length!=0){o=!1,n.sort((a,i)=>(a.sequence??0)<(i.sequence??0)?-1:1);for(let a of n)await this._runTool(a)}}}async _runQuery(){return await this.model.invoke(new f().messages(this.conversation?.messages).tools(this.tools).build())}async _runTool(e){if(this.generateToolNameToIndexMap(),!(e.name in this.toolNameToIndexMap)){this.conversation.append(u.builder().role("tool").toolResult(c.of(e,new D("Agent does not have a tool with this name."))).build());return}let s=this.tools[this.toolNameToIndexMap[e.name]];try{let o=await s.execute(e.parameters);this.conversation.append(u.builder().role("tool").toolResult(c.of(e,o)).build())}catch(o){this.conversation.append(u.builder().role("tool").toolResult(c.of(e,JSON.stringify(o))).build())}}generateToolNameToIndexMap(){if(this.toolNameToIndexMap==null){this.toolNameToIndexMap={};for(let e=0;e<this.tools.length;e++)this.toolNameToIndexMap[this.tools[e].getName()]=e}}static builder(){return new A}}class A{_name;_systemPrompt;_tools;_model;_conversation;_conversationManager=new g;_toolNameToIndexMap;_callback=e=>J(e);name(e){return this._name=e,this}systemPrompt(e){return this._systemPrompt=e,this}tools(e){return this._tools=e,this}addTool(e){return this._tools==null&&(this._tools=[]),this._tools.push(e),this}model(e){return this._model=e,this}conversationManager(e){return this._conversationManager=e,this}callback(e){return this._callback=e,this}build(){let e=new k(this._name,this._tools,this._model,this._conversationManager,this._callback);return this._conversation!=null&&(e.conversation=this._conversation),this._systemPrompt!=null&&(e.systemPrompt=this._systemPrompt),e}}function J(t){for(const e of t.filter(l.Thinking))console.log("\x1B[90m"+e.get()+"\x1B[0m");for(const e of t.filter(l.Content))console.log(e.get());for(const e of t.filter(l.ToolCall))console.log("\x1B[32mCalling Tool: "+e.name+"\x1B[0m")}class d extends Error{constructor(e){super(e),this.name="ToolNotDefinedError"}}class F{getName(){throw new d("Tool name not defined.")}getDescription(){throw new d("Tool description not defined.")}getToolSchema(){throw new d("Tool parameter schema not defined.")}execute(e){return null}}class p{parameters;output;constructor(e,s){this.parameters=e,this.output=s}static builder(){return new O}}class O{_parameters;_output;addParameter(e){return this._parameters==null&&(this._parameters=[]),this._parameters.push(e),this}output(e){return this._output=e,this}build(){return this._parameters==null&&(this._parameters=[]),new p(this._parameters,this._output)}}class y{name;description;type;required;constructor(e,s,o,r){this.name=e,this.description=s,this.type=o,this.required=r,this.assertValidType()}assertValidType(){}static builder(){return new R}}class R{_name;_description;_type;_required;name(e){return this._name=e,this}description(e){return this._description=e,this}type(e){return this._type=e,this}required(e){return this._required=e,this}build(){return this._required==null&&(this._required=!1),new y(this._name,this._description,this._type,this._required)}}class L extends P{endpoint;model;options;constructor(e,s,o){super(),this.endpoint=e,this.model=s,this.options=o}async invoke(e){let s={model:this.model,messages:this._formatMessages(e),tools:this._formatTools(e),...this.options},o=await fetch(this.endpoint+"/api/chat",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!o.ok)throw new Error(`HTTP error! status: ${o.status}`);let r=await o.json(),n=[];if(r.message.tool_calls)for(let a in r.message.tool_calls){const i=r.message.tool_calls[a];let h="function",S=i[h]?.name,E=i[h]?.index,B=i.id??void 0,I=typeof i[h]?.arguments=="string"?JSON.parse(i[h]?.arguments):i[h]?.arguments;n.push(_.builder().name(S).type(h).parameters(I).sequence(E).id(B).build())}return u.builder().toolCalls(n).role(r.message.role).content(r.message.content).thinking(r.message.thinking).build()}_formatTools(e){let s=[];for(let o of e.tools){let r={},n=[];for(let i of o.getToolSchema().parameters)r[i.name]={},r[i.name].type=i.type,r[i.name].description=i.description,i.required&&n.push(i.name);let a={type:"function",function:{name:o.getName(),description:o.getDescription(),parameters:{type:"object",properties:r,required:n}}};s.push(a)}return s}_formatMessages(e){let s=[];for(let o of e.messages){if(o.role=="assistant"||o.role=="system"||o.role=="user"){s.push(this._formatSingleMessage(o));continue}if(o.role=="tool"){for(const r of o.content)if(r.getMessageComponentType()==l.ToolResult){const n=r;s.push({role:o.role,name:n.toolName,content:JSON.stringify(n.toolResult)})}}}return s}_formatSingleMessage(e){let s={role:e.role},o,r,n;for(const a of e.content){if(a.getMessageComponentType()==l.Content){const i=a;o==null&&(o=""),o+=i.get()}if(a.getMessageComponentType()==l.Thinking){const i=a;n==null&&(n=""),n+=i.get()}if(a.getMessageComponentType()==l.ToolCall){const i=a;r==null&&(r=[]),r.push(this._formatToolCall(i))}}return o!=null&&(s.content=o),r!=null&&(s.tool_calls=r),n!=null&&(s.thinking=n),s}_formatToolCall(e){return{function:{name:e.name,arguments:e.parameters}}}}function Q(t){return e=>{e.prototype.getName=()=>t}}function V(t){return e=>{Object.defineProperty(e.prototype,"getDescription",{value:function(){return t},enumerable:!0,configurable:!0,writable:!0})}}function H(t){return e=>{e.prototype.tapewormParams==null&&(e.prototype.tapewormParams=[]),e.prototype.tapewormParamsOutput==null&&(e.prototype.tapewormParamsOutput=""),e.prototype.tapewormParams.push(y.builder().name(t.name).description(t.description).required(t.required).type(t.type).build()),e.prototype.getToolSchema=()=>new p(e.prototype.tapewormParams,e.prototype.tapewormParamsOutput)}}function K(t){return e=>{e.prototype.tapewormParams==null&&(e.prototype.tapewormParams=[]),e.prototype.tapewormParamsOutput==null&&(e.prototype.tapewormParamsOutput=""),e.prototype.tapewormParamsOutput=t,e.prototype.getToolSchema=()=>new p(e.prototype.tapewormParams,e.prototype.tapewormParamsOutput)}}exports.Agent=k;exports.Content=C;exports.Conversation=w;exports.ConversationManager=M;exports.DefaultConversationManager=g;exports.Message=u;exports.MessageBuilder=b;exports.MessageComponent=m;exports.MessageComponentType=l;exports.Model=P;exports.ModelRequest=q;exports.ModelRequestBuilder=f;exports.OllamaModel=L;exports.Parameter=y;exports.ParameterBuilder=R;exports.Thinking=N;exports.Tool=F;exports.ToolCall=_;exports.ToolCallBuilder=x;exports.ToolDescription=V;exports.ToolName=Q;exports.ToolOutput=K;exports.ToolParameter=H;exports.ToolResult=c;exports.ToolSchema=p;exports.ToolSchemaBuilder=O;
@@ -54,7 +54,7 @@ class g extends Error {
54
54
  super(e), this.name = "ConversationManagerNotImplemented";
55
55
  }
56
56
  }
57
- class h {
57
+ class u {
58
58
  role;
59
59
  content;
60
60
  /**
@@ -148,7 +148,7 @@ class k {
148
148
  build() {
149
149
  if (this._content == null || this._content.length == 0)
150
150
  throw new Error("Role-only messages are not supported by Tapeworm.");
151
- return new h(this._role, this._content);
151
+ return new u(this._role, this._content);
152
152
  }
153
153
  }
154
154
  const l = {
@@ -359,8 +359,8 @@ class v extends c {
359
359
  * @param type Type of tool call (e.g., function).
360
360
  * @param id Provider-generated identifier for correlating results.
361
361
  */
362
- constructor(e, s, o, n, r) {
363
- super(), this.sequence = e, this.name = s, this.parameters = o, this.type = n, this.id = r;
362
+ constructor(e, s, o, r, n) {
363
+ super(), this.sequence = e, this.name = s, this.parameters = o, this.type = r, this.id = n;
364
364
  }
365
365
  /**
366
366
  * Convenience factory for a ToolCallBuilder.
@@ -436,16 +436,55 @@ class I extends Error {
436
436
  }
437
437
  }
438
438
  class j {
439
+ /**
440
+ * The name of the agent.
441
+ */
439
442
  name;
443
+ /**
444
+ * The system prompt (if any) for the agent.
445
+ */
440
446
  systemPrompt;
447
+ /**
448
+ * The tools this agent knows about and can run.
449
+ */
441
450
  tools;
451
+ /**
452
+ * The underlying model for the agent.
453
+ */
442
454
  model;
455
+ /**
456
+ * The conversation for the agent.
457
+ * You do not normally need to set this parameter unless you are building a use case
458
+ * where you have a persistent session with an agent.
459
+ */
443
460
  conversation;
461
+ /**
462
+ * The conversation manager for the agent.
463
+ * Normally, a converstation manager that does nothing will be used.
464
+ * When SummarizingConversationManager or RAGConversationManager is implemented, these will help you avoid
465
+ * token overflow.
466
+ */
444
467
  conversationManager;
468
+ /**
469
+ * A cache for looking up tools in the Tools array.
470
+ * DO NOT MANUALLY SET THIS VALUE. AGENT AUTOMATICALLY TAKES CARE OF IT.
471
+ */
445
472
  toolNameToIndexMap;
473
+ /**
474
+ * The callback function, invoked for every response from the model.
475
+ * The default implementation just prints to std.out or your console.
476
+ */
446
477
  callback;
447
- constructor(e, s, o, n, r) {
448
- this.name = e, this.model = o, this.conversationManager = n, this.tools = s, this.callback = r, this.conversationManager.configure(o);
478
+ /**
479
+ * This is the constructor for an Agent.
480
+ *
481
+ * i IMPLORE YOU not to use this method. You CAN, but you should be using the Builder instead
482
+ * for the best results, as this method WILL change with future updates.
483
+ *
484
+ * Builder will be a lot more stable and will always be backwards compatible.
485
+ */
486
+ constructor(e, s, o, r, n) {
487
+ this.name = e, this.model = o, this.conversationManager = r, this.tools = s, this.callback = n, this.conversationManager.configure(o);
449
488
  }
450
489
  /**
451
490
  * Run the full agent loop for a user query: seed the conversation, invoke the model,
@@ -456,20 +495,20 @@ class j {
456
495
  */
457
496
  async invoke(e, s = this.callback) {
458
497
  this.conversation == null && (this.conversation = new x(), this.conversationManager != null && (this.conversation.manager = this.conversationManager), this.systemPrompt != null && this.conversation.append(
459
- h.builder().role("system").content(this.systemPrompt).build()
498
+ u.builder().role("system").content(this.systemPrompt).build()
460
499
  )), this.conversation.append(
461
- h.builder().role("user").content(e).build()
500
+ u.builder().role("user").content(e).build()
462
501
  );
463
502
  let o = !1;
464
503
  for (; !o; ) {
465
- let n = await this._runQuery();
466
- s(n), this.conversation.append(n), o = !0;
467
- const r = n.filter(
504
+ let r = await this._runQuery();
505
+ s(r), this.conversation.append(r), o = !0;
506
+ const n = r.filter(
468
507
  l.ToolCall
469
508
  );
470
- if (r != null && r.length != 0) {
471
- o = !1, r.sort((a, i) => (a.sequence ?? 0) < (i.sequence ?? 0) ? -1 : 1);
472
- for (let a of r)
509
+ if (n != null && n.length != 0) {
510
+ o = !1, n.sort((a, i) => (a.sequence ?? 0) < (i.sequence ?? 0) ? -1 : 1);
511
+ for (let a of n)
473
512
  await this._runTool(a);
474
513
  }
475
514
  }
@@ -491,7 +530,7 @@ class j {
491
530
  async _runTool(e) {
492
531
  if (this.generateToolNameToIndexMap(), !(e.name in this.toolNameToIndexMap)) {
493
532
  this.conversation.append(
494
- h.builder().role("tool").toolResult(
533
+ u.builder().role("tool").toolResult(
495
534
  m.of(
496
535
  e,
497
536
  new I(
@@ -506,11 +545,11 @@ class j {
506
545
  try {
507
546
  let o = await s.execute(e.parameters);
508
547
  this.conversation.append(
509
- h.builder().role("tool").toolResult(m.of(e, o)).build()
548
+ u.builder().role("tool").toolResult(m.of(e, o)).build()
510
549
  );
511
550
  } catch (o) {
512
551
  this.conversation.append(
513
- h.builder().role("tool").toolResult(m.of(e, JSON.stringify(o))).build()
552
+ u.builder().role("tool").toolResult(m.of(e, JSON.stringify(o))).build()
514
553
  );
515
554
  }
516
555
  }
@@ -524,6 +563,9 @@ class j {
524
563
  this.toolNameToIndexMap[this.tools[e].getName()] = e;
525
564
  }
526
565
  }
566
+ /**
567
+ * Get a builder to build an Agent.
568
+ */
527
569
  static builder() {
528
570
  return new B();
529
571
  }
@@ -537,27 +579,51 @@ class B {
537
579
  _conversationManager = new _();
538
580
  _toolNameToIndexMap;
539
581
  _callback = (e) => D(e);
582
+ /**
583
+ * Set the name of the agent.
584
+ */
540
585
  name(e) {
541
586
  return this._name = e, this;
542
587
  }
588
+ /**
589
+ * Set the system prompt of the agent.
590
+ */
543
591
  systemPrompt(e) {
544
592
  return this._systemPrompt = e, this;
545
593
  }
594
+ /**
595
+ * Set the tools of the agent, if you already have an array of tools.
596
+ */
546
597
  tools(e) {
547
598
  return this._tools = e, this;
548
599
  }
600
+ /**
601
+ * Add a tool, 1 by 1, to the agent..
602
+ */
549
603
  addTool(e) {
550
604
  return this._tools == null && (this._tools = []), this._tools.push(e), this;
551
605
  }
606
+ /**
607
+ * Set the underlying model for the agent.
608
+ */
552
609
  model(e) {
553
610
  return this._model = e, this;
554
611
  }
612
+ /**
613
+ * Set the conversation manager for the agent.
614
+ */
555
615
  conversationManager(e) {
556
616
  return this._conversationManager = e, this;
557
617
  }
618
+ /**
619
+ * Set the callback for the agent.
620
+ */
558
621
  callback(e) {
559
622
  return this._callback = e, this;
560
623
  }
624
+ /**
625
+ * Build the agent.
626
+ */
561
627
  build() {
562
628
  let e = new j(
563
629
  this._name,
@@ -583,15 +649,6 @@ class p extends Error {
583
649
  }
584
650
  }
585
651
  class F {
586
- name;
587
- description;
588
- tool_schema;
589
- /**
590
- * Initialize tool metadata from subclass implementations.
591
- */
592
- constructor() {
593
- this.name = this.getName(), this.description = this.getDescription(), this.tool_schema = this.getToolSchema();
594
- }
595
652
  /**
596
653
  * Name that uniquely identifies this tool.
597
654
  * @returns A short, stable identifier string.
@@ -681,8 +738,8 @@ class T {
681
738
  * @param type JSON-serializable type name (e.g., string, number).
682
739
  * @param required Whether the parameter must be provided.
683
740
  */
684
- constructor(e, s, o, n) {
685
- this.name = e, this.description = s, this.type = o, this.required = n, this.assertValidType();
741
+ constructor(e, s, o, r) {
742
+ this.name = e, this.description = s, this.type = o, this.required = r, this.assertValidType();
686
743
  }
687
744
  /**
688
745
  * Placeholder for validating supported parameter types.
@@ -775,16 +832,16 @@ class L extends O {
775
832
  });
776
833
  if (!o.ok)
777
834
  throw new Error(`HTTP error! status: ${o.status}`);
778
- let n = await o.json(), r = [];
779
- if (n.message.tool_calls)
780
- for (let a in n.message.tool_calls) {
781
- const i = n.message.tool_calls[a];
782
- let u = "function", w = i[u]?.name, b = i[u]?.index, M = i.id ?? void 0, N = typeof i[u]?.arguments == "string" ? JSON.parse(i[u]?.arguments) : i[u]?.arguments;
783
- r.push(
784
- v.builder().name(w).type(u).parameters(N).sequence(b).id(M).build()
835
+ let r = await o.json(), n = [];
836
+ if (r.message.tool_calls)
837
+ for (let a in r.message.tool_calls) {
838
+ const i = r.message.tool_calls[a];
839
+ let h = "function", w = i[h]?.name, b = i[h]?.index, M = i.id ?? void 0, N = typeof i[h]?.arguments == "string" ? JSON.parse(i[h]?.arguments) : i[h]?.arguments;
840
+ n.push(
841
+ v.builder().name(w).type(h).parameters(N).sequence(b).id(M).build()
785
842
  );
786
843
  }
787
- return h.builder().toolCalls(r).role(n.message.role).content(n.message.content).thinking(n.message.thinking).build();
844
+ return u.builder().toolCalls(n).role(r.message.role).content(r.message.content).thinking(r.message.thinking).build();
788
845
  }
789
846
  /**
790
847
  * Convert internal tool definitions into the JSON schema format expected by Ollama.
@@ -794,9 +851,9 @@ class L extends O {
794
851
  _formatTools(e) {
795
852
  let s = [];
796
853
  for (let o of e.tools) {
797
- let n = {}, r = [];
854
+ let r = {}, n = [];
798
855
  for (let i of o.getToolSchema().parameters)
799
- n[i.name] = {}, n[i.name].type = i.type, n[i.name].description = i.description, i.required && r.push(i.name);
856
+ r[i.name] = {}, r[i.name].type = i.type, r[i.name].description = i.description, i.required && n.push(i.name);
800
857
  let a = {
801
858
  type: "function",
802
859
  function: {
@@ -804,8 +861,8 @@ class L extends O {
804
861
  description: o.getDescription(),
805
862
  parameters: {
806
863
  type: "object",
807
- properties: n,
808
- required: r
864
+ properties: r,
865
+ required: n
809
866
  }
810
867
  }
811
868
  };
@@ -827,13 +884,13 @@ class L extends O {
827
884
  continue;
828
885
  }
829
886
  if (o.role == "tool") {
830
- for (const n of o.content)
831
- if (n.getMessageComponentType() == l.ToolResult) {
832
- const r = n;
887
+ for (const r of o.content)
888
+ if (r.getMessageComponentType() == l.ToolResult) {
889
+ const n = r;
833
890
  s.push({
834
891
  role: o.role,
835
- name: r.toolName,
836
- content: JSON.stringify(r.toolResult)
892
+ name: n.toolName,
893
+ content: JSON.stringify(n.toolResult)
837
894
  });
838
895
  }
839
896
  }
@@ -848,7 +905,7 @@ class L extends O {
848
905
  _formatSingleMessage(e) {
849
906
  let s = {
850
907
  role: e.role
851
- }, o, n, r;
908
+ }, o, r, n;
852
909
  for (const a of e.content) {
853
910
  if (a.getMessageComponentType() == l.Content) {
854
911
  const i = a;
@@ -856,14 +913,14 @@ class L extends O {
856
913
  }
857
914
  if (a.getMessageComponentType() == l.Thinking) {
858
915
  const i = a;
859
- r == null && (r = ""), r += i.get();
916
+ n == null && (n = ""), n += i.get();
860
917
  }
861
918
  if (a.getMessageComponentType() == l.ToolCall) {
862
919
  const i = a;
863
- n == null && (n = []), n.push(this._formatToolCall(i));
920
+ r == null && (r = []), r.push(this._formatToolCall(i));
864
921
  }
865
922
  }
866
- return o != null && (s.content = o), n != null && (s.tool_calls = n), r != null && (s.thinking = r), s;
923
+ return o != null && (s.content = o), r != null && (s.tool_calls = r), n != null && (s.thinking = n), s;
867
924
  }
868
925
  /**
869
926
  * Convert a ToolCall into the structure Ollama expects.
@@ -920,7 +977,7 @@ export {
920
977
  x as Conversation,
921
978
  P as ConversationManager,
922
979
  _ as DefaultConversationManager,
923
- h as Message,
980
+ u as Message,
924
981
  k as MessageBuilder,
925
982
  c as MessageComponent,
926
983
  l as MessageComponentType,
@@ -1 +1 @@
1
- (function(n,m){typeof exports=="object"&&typeof module<"u"?m(exports):typeof define=="function"&&define.amd?define(["exports"],m):(n=typeof globalThis<"u"?globalThis:n||self,m(n.Tapeworm={}))})(this,(function(n){"use strict";class m{messages;manager;constructor(){this.messages=[],this.manager=new f}append(e){this.messages.push(e),this.messages=this.manager.compact(this.messages)}}class w{compact(e){throw new M("No implementation for conversation manager!")}configure(e){throw new M("No implementation for conversation manager!")}}class f extends w{compact(e){return e}configure(e){}}class M extends Error{constructor(e){super(e),this.name="ConversationManagerNotImplemented"}}class h{role;content;constructor(e,s){this.role=e,this.content=s}static builder(){return new b}filter(e){return this.content.filter(s=>s.getMessageComponentType()==e)}}class b{_role;_content;role(e){return this._role=e,this}init(){this._content==null&&(this._content=[])}toolCall(e){return e==null?this:(this.init(),this._content.push(e),this)}toolCalls(e){if(e==null)return this;this.init();for(const s of e)this._content.push(s);return this}toolResult(e){return e==null?this:(this.init(),this._content.push(e),this)}thinking(e){return e==null?this:(this.init(),this._content.push(C.of(e)),this)}content(e){return e==null?this:(this.init(),this._content.push(N.of(e)),this)}build(){if(this._content==null||this._content.length==0)throw new Error("Role-only messages are not supported by Tapeworm.");return new h(this._role,this._content)}}const u={Content:"content",Thinking:"thinking",ToolCall:"toolcall",ToolResult:"toolresult"};class p{getMessageComponentType(){throw new Error("Message components that do not have a message component type are not allowed.")}}class N extends p{text;constructor(e){super(),this.text=e}getMessageComponentType(){return u.Content}get(){return this.text}static of(e){return new this(e)}}class C extends p{thought;constructor(e){super(),this.thought=e}getMessageComponentType(){return u.Thinking}get(){return this.thought}static of(e){return new this(e)}}class d extends p{id;toolName;toolResult;constructor(e,s,o){super(),this.id=e,this.toolName=s,this.toolResult=o}getMessageComponentType(){return u.ToolResult}static of(e,s){return new this(e.id,e.name,s)}}class P{async invoke(e){throw new k("The invoke function for this model was not correctly implemented.")}tokenLimit(){throw new k("The tokenLimit function for this model was not correctly implemented.")}}class q{messages;tools;constructor(e,s){this.messages=e,this.tools=s}static builder(){return new _}}class _{_messages;_tools;messages(e){return this._messages=e,this}tools(e){return this._tools=e,this}build(){if(this._tools==null&&(this._tools=[]),this._messages==null)throw new B("Requests to the model should include content.");return new q(this._messages,this._tools)}}class k extends Error{constructor(e){super(e),this.name="ModelNotImplementedError"}}class B extends Error{constructor(e){super(e),this.name="MessagesNotDefinedError"}}class T extends p{sequence;name;parameters;type;id;getMessageComponentType(){return u.ToolCall}constructor(e,s,o,r,i){super(),this.sequence=e,this.name=s,this.parameters=o,this.type=r,this.id=i}static builder(){return new O}}class O{_sequence;_name;_parameters;_type;_id;sequence(e){return this._sequence=e,this}name(e){return this._name=e,this}parameters(e){return this._parameters=e,this}type(e){return this._type=e,this}id(e){return e!=null&&(this._id=e),this}build(){return this._sequence==null&&(this._sequence=0),this._id==null&&(this._id=(Math.random()+1).toString(36).slice(2,7)),new T(this._sequence,this._name,this._parameters,this._type,this._id)}}class j extends Error{constructor(e){super(e),this.name="ToolNotFoundError"}}class S{name;systemPrompt;tools;model;conversation;conversationManager;toolNameToIndexMap;callback;constructor(e,s,o,r,i){this.name=e,this.model=o,this.conversationManager=r,this.tools=s,this.callback=i,this.conversationManager.configure(o)}async invoke(e,s=this.callback){this.conversation==null&&(this.conversation=new m,this.conversationManager!=null&&(this.conversation.manager=this.conversationManager),this.systemPrompt!=null&&this.conversation.append(h.builder().role("system").content(this.systemPrompt).build())),this.conversation.append(h.builder().role("user").content(e).build());let o=!1;for(;!o;){let r=await this._runQuery();s(r),this.conversation.append(r),o=!0;const i=r.filter(u.ToolCall);if(i!=null&&i.length!=0){o=!1,i.sort((l,a)=>(l.sequence??0)<(a.sequence??0)?-1:1);for(let l of i)await this._runTool(l)}}}async _runQuery(){return await this.model.invoke(new _().messages(this.conversation?.messages).tools(this.tools).build())}async _runTool(e){if(this.generateToolNameToIndexMap(),!(e.name in this.toolNameToIndexMap)){this.conversation.append(h.builder().role("tool").toolResult(d.of(e,new j("Agent does not have a tool with this name."))).build());return}let s=this.tools[this.toolNameToIndexMap[e.name]];try{let o=await s.execute(e.parameters);this.conversation.append(h.builder().role("tool").toolResult(d.of(e,o)).build())}catch(o){this.conversation.append(h.builder().role("tool").toolResult(d.of(e,JSON.stringify(o))).build())}}generateToolNameToIndexMap(){if(this.toolNameToIndexMap==null){this.toolNameToIndexMap={};for(let e=0;e<this.tools.length;e++)this.toolNameToIndexMap[this.tools[e].getName()]=e}}static builder(){return new I}}class I{_name;_systemPrompt;_tools;_model;_conversation;_conversationManager=new f;_toolNameToIndexMap;_callback=e=>D(e);name(e){return this._name=e,this}systemPrompt(e){return this._systemPrompt=e,this}tools(e){return this._tools=e,this}addTool(e){return this._tools==null&&(this._tools=[]),this._tools.push(e),this}model(e){return this._model=e,this}conversationManager(e){return this._conversationManager=e,this}callback(e){return this._callback=e,this}build(){let e=new S(this._name,this._tools,this._model,this._conversationManager,this._callback);return this._conversation!=null&&(e.conversation=this._conversation),this._systemPrompt!=null&&(e.systemPrompt=this._systemPrompt),e}}function D(t){for(const e of t.filter(u.Thinking))console.log("\x1B[90m"+e.get()+"\x1B[0m");for(const e of t.filter(u.Content))console.log(e.get());for(const e of t.filter(u.ToolCall))console.log("\x1B[32mCalling Tool: "+e.name+"\x1B[0m")}class y extends Error{constructor(e){super(e),this.name="ToolNotDefinedError"}}class x{name;description;tool_schema;constructor(){this.name=this.getName(),this.description=this.getDescription(),this.tool_schema=this.getToolSchema()}getName(){throw new y("Tool name not defined.")}getDescription(){throw new y("Tool description not defined.")}getToolSchema(){throw new y("Tool parameter schema not defined.")}execute(e){return null}}class g{parameters;output;constructor(e,s){this.parameters=e,this.output=s}static builder(){return new R}}class R{_parameters;_output;addParameter(e){return this._parameters==null&&(this._parameters=[]),this._parameters.push(e),this}output(e){return this._output=e,this}build(){return this._parameters==null&&(this._parameters=[]),new g(this._parameters,this._output)}}class v{name;description;type;required;constructor(e,s,o,r){this.name=e,this.description=s,this.type=o,this.required=r,this.assertValidType()}assertValidType(){}static builder(){return new E}}class E{_name;_description;_type;_required;name(e){return this._name=e,this}description(e){return this._description=e,this}type(e){return this._type=e,this}required(e){return this._required=e,this}build(){return this._required==null&&(this._required=!1),new v(this._name,this._description,this._type,this._required)}}class A extends P{endpoint;model;options;constructor(e,s,o){super(),this.endpoint=e,this.model=s,this.options=o}async invoke(e){let s={model:this.model,messages:this._formatMessages(e),tools:this._formatTools(e),...this.options},o=await fetch(this.endpoint+"/api/chat",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!o.ok)throw new Error(`HTTP error! status: ${o.status}`);let r=await o.json(),i=[];if(r.message.tool_calls)for(let l in r.message.tool_calls){const a=r.message.tool_calls[l];let c="function",V=a[c]?.name,H=a[c]?.index,K=a.id??void 0,W=typeof a[c]?.arguments=="string"?JSON.parse(a[c]?.arguments):a[c]?.arguments;i.push(T.builder().name(V).type(c).parameters(W).sequence(H).id(K).build())}return h.builder().toolCalls(i).role(r.message.role).content(r.message.content).thinking(r.message.thinking).build()}_formatTools(e){let s=[];for(let o of e.tools){let r={},i=[];for(let a of o.getToolSchema().parameters)r[a.name]={},r[a.name].type=a.type,r[a.name].description=a.description,a.required&&i.push(a.name);let l={type:"function",function:{name:o.getName(),description:o.getDescription(),parameters:{type:"object",properties:r,required:i}}};s.push(l)}return s}_formatMessages(e){let s=[];for(let o of e.messages){if(o.role=="assistant"||o.role=="system"||o.role=="user"){s.push(this._formatSingleMessage(o));continue}if(o.role=="tool"){for(const r of o.content)if(r.getMessageComponentType()==u.ToolResult){const i=r;s.push({role:o.role,name:i.toolName,content:JSON.stringify(i.toolResult)})}}}return s}_formatSingleMessage(e){let s={role:e.role},o,r,i;for(const l of e.content){if(l.getMessageComponentType()==u.Content){const a=l;o==null&&(o=""),o+=a.get()}if(l.getMessageComponentType()==u.Thinking){const a=l;i==null&&(i=""),i+=a.get()}if(l.getMessageComponentType()==u.ToolCall){const a=l;r==null&&(r=[]),r.push(this._formatToolCall(a))}}return o!=null&&(s.content=o),r!=null&&(s.tool_calls=r),i!=null&&(s.thinking=i),s}_formatToolCall(e){return{function:{name:e.name,arguments:e.parameters}}}}function J(t){return e=>{e.prototype.getName=()=>t}}function F(t){return e=>{Object.defineProperty(e.prototype,"getDescription",{value:function(){return t},enumerable:!0,configurable:!0,writable:!0})}}function L(t){return e=>{e.prototype.tapewormParams==null&&(e.prototype.tapewormParams=[]),e.prototype.tapewormParamsOutput==null&&(e.prototype.tapewormParamsOutput=""),e.prototype.tapewormParams.push(v.builder().name(t.name).description(t.description).required(t.required).type(t.type).build()),e.prototype.getToolSchema=()=>new g(e.prototype.tapewormParams,e.prototype.tapewormParamsOutput)}}function Q(t){return e=>{e.prototype.tapewormParams==null&&(e.prototype.tapewormParams=[]),e.prototype.tapewormParamsOutput==null&&(e.prototype.tapewormParamsOutput=""),e.prototype.tapewormParamsOutput=t,e.prototype.getToolSchema=()=>new g(e.prototype.tapewormParams,e.prototype.tapewormParamsOutput)}}n.Agent=S,n.Content=N,n.Conversation=m,n.ConversationManager=w,n.DefaultConversationManager=f,n.Message=h,n.MessageBuilder=b,n.MessageComponent=p,n.MessageComponentType=u,n.Model=P,n.ModelRequest=q,n.ModelRequestBuilder=_,n.OllamaModel=A,n.Parameter=v,n.ParameterBuilder=E,n.Thinking=C,n.Tool=x,n.ToolCall=T,n.ToolCallBuilder=O,n.ToolDescription=F,n.ToolName=J,n.ToolOutput=Q,n.ToolParameter=L,n.ToolResult=d,n.ToolSchema=g,n.ToolSchemaBuilder=R,Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})}));
1
+ (function(n,m){typeof exports=="object"&&typeof module<"u"?m(exports):typeof define=="function"&&define.amd?define(["exports"],m):(n=typeof globalThis<"u"?globalThis:n||self,m(n.Tapeworm={}))})(this,(function(n){"use strict";class m{messages;manager;constructor(){this.messages=[],this.manager=new f}append(e){this.messages.push(e),this.messages=this.manager.compact(this.messages)}}class w{compact(e){throw new M("No implementation for conversation manager!")}configure(e){throw new M("No implementation for conversation manager!")}}class f extends w{compact(e){return e}configure(e){}}class M extends Error{constructor(e){super(e),this.name="ConversationManagerNotImplemented"}}class h{role;content;constructor(e,s){this.role=e,this.content=s}static builder(){return new b}filter(e){return this.content.filter(s=>s.getMessageComponentType()==e)}}class b{_role;_content;role(e){return this._role=e,this}init(){this._content==null&&(this._content=[])}toolCall(e){return e==null?this:(this.init(),this._content.push(e),this)}toolCalls(e){if(e==null)return this;this.init();for(const s of e)this._content.push(s);return this}toolResult(e){return e==null?this:(this.init(),this._content.push(e),this)}thinking(e){return e==null?this:(this.init(),this._content.push(N.of(e)),this)}content(e){return e==null?this:(this.init(),this._content.push(C.of(e)),this)}build(){if(this._content==null||this._content.length==0)throw new Error("Role-only messages are not supported by Tapeworm.");return new h(this._role,this._content)}}const u={Content:"content",Thinking:"thinking",ToolCall:"toolcall",ToolResult:"toolresult"};class p{getMessageComponentType(){throw new Error("Message components that do not have a message component type are not allowed.")}}class C extends p{text;constructor(e){super(),this.text=e}getMessageComponentType(){return u.Content}get(){return this.text}static of(e){return new this(e)}}class N extends p{thought;constructor(e){super(),this.thought=e}getMessageComponentType(){return u.Thinking}get(){return this.thought}static of(e){return new this(e)}}class d extends p{id;toolName;toolResult;constructor(e,s,o){super(),this.id=e,this.toolName=s,this.toolResult=o}getMessageComponentType(){return u.ToolResult}static of(e,s){return new this(e.id,e.name,s)}}class P{async invoke(e){throw new k("The invoke function for this model was not correctly implemented.")}tokenLimit(){throw new k("The tokenLimit function for this model was not correctly implemented.")}}class q{messages;tools;constructor(e,s){this.messages=e,this.tools=s}static builder(){return new _}}class _{_messages;_tools;messages(e){return this._messages=e,this}tools(e){return this._tools=e,this}build(){if(this._tools==null&&(this._tools=[]),this._messages==null)throw new B("Requests to the model should include content.");return new q(this._messages,this._tools)}}class k extends Error{constructor(e){super(e),this.name="ModelNotImplementedError"}}class B extends Error{constructor(e){super(e),this.name="MessagesNotDefinedError"}}class T extends p{sequence;name;parameters;type;id;getMessageComponentType(){return u.ToolCall}constructor(e,s,o,r,i){super(),this.sequence=e,this.name=s,this.parameters=o,this.type=r,this.id=i}static builder(){return new O}}class O{_sequence;_name;_parameters;_type;_id;sequence(e){return this._sequence=e,this}name(e){return this._name=e,this}parameters(e){return this._parameters=e,this}type(e){return this._type=e,this}id(e){return e!=null&&(this._id=e),this}build(){return this._sequence==null&&(this._sequence=0),this._id==null&&(this._id=(Math.random()+1).toString(36).slice(2,7)),new T(this._sequence,this._name,this._parameters,this._type,this._id)}}class j extends Error{constructor(e){super(e),this.name="ToolNotFoundError"}}class R{name;systemPrompt;tools;model;conversation;conversationManager;toolNameToIndexMap;callback;constructor(e,s,o,r,i){this.name=e,this.model=o,this.conversationManager=r,this.tools=s,this.callback=i,this.conversationManager.configure(o)}async invoke(e,s=this.callback){this.conversation==null&&(this.conversation=new m,this.conversationManager!=null&&(this.conversation.manager=this.conversationManager),this.systemPrompt!=null&&this.conversation.append(h.builder().role("system").content(this.systemPrompt).build())),this.conversation.append(h.builder().role("user").content(e).build());let o=!1;for(;!o;){let r=await this._runQuery();s(r),this.conversation.append(r),o=!0;const i=r.filter(u.ToolCall);if(i!=null&&i.length!=0){o=!1,i.sort((l,a)=>(l.sequence??0)<(a.sequence??0)?-1:1);for(let l of i)await this._runTool(l)}}}async _runQuery(){return await this.model.invoke(new _().messages(this.conversation?.messages).tools(this.tools).build())}async _runTool(e){if(this.generateToolNameToIndexMap(),!(e.name in this.toolNameToIndexMap)){this.conversation.append(h.builder().role("tool").toolResult(d.of(e,new j("Agent does not have a tool with this name."))).build());return}let s=this.tools[this.toolNameToIndexMap[e.name]];try{let o=await s.execute(e.parameters);this.conversation.append(h.builder().role("tool").toolResult(d.of(e,o)).build())}catch(o){this.conversation.append(h.builder().role("tool").toolResult(d.of(e,JSON.stringify(o))).build())}}generateToolNameToIndexMap(){if(this.toolNameToIndexMap==null){this.toolNameToIndexMap={};for(let e=0;e<this.tools.length;e++)this.toolNameToIndexMap[this.tools[e].getName()]=e}}static builder(){return new I}}class I{_name;_systemPrompt;_tools;_model;_conversation;_conversationManager=new f;_toolNameToIndexMap;_callback=e=>D(e);name(e){return this._name=e,this}systemPrompt(e){return this._systemPrompt=e,this}tools(e){return this._tools=e,this}addTool(e){return this._tools==null&&(this._tools=[]),this._tools.push(e),this}model(e){return this._model=e,this}conversationManager(e){return this._conversationManager=e,this}callback(e){return this._callback=e,this}build(){let e=new R(this._name,this._tools,this._model,this._conversationManager,this._callback);return this._conversation!=null&&(e.conversation=this._conversation),this._systemPrompt!=null&&(e.systemPrompt=this._systemPrompt),e}}function D(t){for(const e of t.filter(u.Thinking))console.log("\x1B[90m"+e.get()+"\x1B[0m");for(const e of t.filter(u.Content))console.log(e.get());for(const e of t.filter(u.ToolCall))console.log("\x1B[32mCalling Tool: "+e.name+"\x1B[0m")}class y extends Error{constructor(e){super(e),this.name="ToolNotDefinedError"}}class x{getName(){throw new y("Tool name not defined.")}getDescription(){throw new y("Tool description not defined.")}getToolSchema(){throw new y("Tool parameter schema not defined.")}execute(e){return null}}class g{parameters;output;constructor(e,s){this.parameters=e,this.output=s}static builder(){return new S}}class S{_parameters;_output;addParameter(e){return this._parameters==null&&(this._parameters=[]),this._parameters.push(e),this}output(e){return this._output=e,this}build(){return this._parameters==null&&(this._parameters=[]),new g(this._parameters,this._output)}}class v{name;description;type;required;constructor(e,s,o,r){this.name=e,this.description=s,this.type=o,this.required=r,this.assertValidType()}assertValidType(){}static builder(){return new E}}class E{_name;_description;_type;_required;name(e){return this._name=e,this}description(e){return this._description=e,this}type(e){return this._type=e,this}required(e){return this._required=e,this}build(){return this._required==null&&(this._required=!1),new v(this._name,this._description,this._type,this._required)}}class A extends P{endpoint;model;options;constructor(e,s,o){super(),this.endpoint=e,this.model=s,this.options=o}async invoke(e){let s={model:this.model,messages:this._formatMessages(e),tools:this._formatTools(e),...this.options},o=await fetch(this.endpoint+"/api/chat",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!o.ok)throw new Error(`HTTP error! status: ${o.status}`);let r=await o.json(),i=[];if(r.message.tool_calls)for(let l in r.message.tool_calls){const a=r.message.tool_calls[l];let c="function",V=a[c]?.name,H=a[c]?.index,K=a.id??void 0,W=typeof a[c]?.arguments=="string"?JSON.parse(a[c]?.arguments):a[c]?.arguments;i.push(T.builder().name(V).type(c).parameters(W).sequence(H).id(K).build())}return h.builder().toolCalls(i).role(r.message.role).content(r.message.content).thinking(r.message.thinking).build()}_formatTools(e){let s=[];for(let o of e.tools){let r={},i=[];for(let a of o.getToolSchema().parameters)r[a.name]={},r[a.name].type=a.type,r[a.name].description=a.description,a.required&&i.push(a.name);let l={type:"function",function:{name:o.getName(),description:o.getDescription(),parameters:{type:"object",properties:r,required:i}}};s.push(l)}return s}_formatMessages(e){let s=[];for(let o of e.messages){if(o.role=="assistant"||o.role=="system"||o.role=="user"){s.push(this._formatSingleMessage(o));continue}if(o.role=="tool"){for(const r of o.content)if(r.getMessageComponentType()==u.ToolResult){const i=r;s.push({role:o.role,name:i.toolName,content:JSON.stringify(i.toolResult)})}}}return s}_formatSingleMessage(e){let s={role:e.role},o,r,i;for(const l of e.content){if(l.getMessageComponentType()==u.Content){const a=l;o==null&&(o=""),o+=a.get()}if(l.getMessageComponentType()==u.Thinking){const a=l;i==null&&(i=""),i+=a.get()}if(l.getMessageComponentType()==u.ToolCall){const a=l;r==null&&(r=[]),r.push(this._formatToolCall(a))}}return o!=null&&(s.content=o),r!=null&&(s.tool_calls=r),i!=null&&(s.thinking=i),s}_formatToolCall(e){return{function:{name:e.name,arguments:e.parameters}}}}function J(t){return e=>{e.prototype.getName=()=>t}}function F(t){return e=>{Object.defineProperty(e.prototype,"getDescription",{value:function(){return t},enumerable:!0,configurable:!0,writable:!0})}}function L(t){return e=>{e.prototype.tapewormParams==null&&(e.prototype.tapewormParams=[]),e.prototype.tapewormParamsOutput==null&&(e.prototype.tapewormParamsOutput=""),e.prototype.tapewormParams.push(v.builder().name(t.name).description(t.description).required(t.required).type(t.type).build()),e.prototype.getToolSchema=()=>new g(e.prototype.tapewormParams,e.prototype.tapewormParamsOutput)}}function Q(t){return e=>{e.prototype.tapewormParams==null&&(e.prototype.tapewormParams=[]),e.prototype.tapewormParamsOutput==null&&(e.prototype.tapewormParamsOutput=""),e.prototype.tapewormParamsOutput=t,e.prototype.getToolSchema=()=>new g(e.prototype.tapewormParams,e.prototype.tapewormParamsOutput)}}n.Agent=R,n.Content=C,n.Conversation=m,n.ConversationManager=w,n.DefaultConversationManager=f,n.Message=h,n.MessageBuilder=b,n.MessageComponent=p,n.MessageComponentType=u,n.Model=P,n.ModelRequest=q,n.ModelRequestBuilder=_,n.OllamaModel=A,n.Parameter=v,n.ParameterBuilder=E,n.Thinking=N,n.Tool=x,n.ToolCall=T,n.ToolCallBuilder=O,n.ToolDescription=F,n.ToolName=J,n.ToolOutput=Q,n.ToolParameter=L,n.ToolResult=d,n.ToolSchema=g,n.ToolSchemaBuilder=S,Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})}));
@@ -1,16 +1,13 @@
1
+ /**
2
+ * The Tool module contains the Tool class, which shows
3
+ * what properties are required by a class to be invocable by Tapeworm.
4
+ */
1
5
  import type ToolSchema from "./toolschema";
2
6
  /**
3
7
  * The Tool class represents a tool that a Tapeworm agent can use.
4
8
  *
5
9
  */
6
10
  export default class Tool {
7
- private name;
8
- private description;
9
- private tool_schema;
10
- /**
11
- * Initialize tool metadata from subclass implementations.
12
- */
13
- constructor();
14
11
  /**
15
12
  * Name that uniquely identifies this tool.
16
13
  * @returns A short, stable identifier string.
@@ -1,3 +1,11 @@
1
+ /**
2
+ * This module is dedicated to just the ToolCall MessageComponent.
3
+ *
4
+ * The reason is that it's the most complicated MessageComponent and deserves to have its own file,
5
+ * as this class contains more ways to instantiate than normal MessageComponents.
6
+ *
7
+ * @module
8
+ */
1
9
  import { MessageComponent, MessageComponentType } from "../conversation/message";
2
10
  /**
3
11
  * Represents a single tool invocation returned by a model, including the target
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * They are different from the Babel decorators in @atgs/babel-plugin-tapeworm-decorator, but they achieve the same functionality.
5
5
  *
6
- *
6
+ * @module
7
7
  */
8
8
  export declare function ToolName(name: String): (toolClass: Function) => void;
9
9
  export declare function ToolDescription(description: String): (toolClass: Function) => void;
@@ -1,5 +1,17 @@
1
1
  /**
2
- * Tool schemas specify the input and output of a tool.
2
+ * This module contains everything related to tool schemas.
3
+ *
4
+ * Enclosed are the ToolSchema (and builder) and Parameter (and builder) classes.
5
+ *
6
+ * @module
7
+ */
8
+ /**
9
+ * ToolSchemas define the input and output of a tool.
10
+ *
11
+ * They consist of a list of parameters and a description of the output of the tool.
12
+ *
13
+ * You can build these using ToolSchemaBuilder, but it can be more pragmatic to use
14
+ * the Typescript or Babel decorators instead, as they will automatically generate a ToolSchema for you.
3
15
  */
4
16
  export default class ToolSchema {
5
17
  parameters: Parameter[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atgs/tapeworm",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "type": "module",
5
5
  "main": "dist/tapeworm.cjs.js",
6
6
  "module": "dist/tapeworm.es.js",
@@ -15,7 +15,8 @@
15
15
  "README.md"
16
16
  ],
17
17
  "scripts": {
18
- "build": "npm run format && npm run test && vite build && npm run build:types",
18
+ "build": "npm run format && npm run test && vite build && npm run build:types && npm run docs",
19
+ "docs": "typedoc --options typedoc.json",
19
20
  "build:types": "tsc -p tsconfig.types.json",
20
21
  "test": "jest",
21
22
  "format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,css,md}\""
@@ -27,6 +28,8 @@
27
28
  "jest": "^30.2.0",
28
29
  "prettier": "^3.7.4",
29
30
  "ts-node": "^10.9.2",
31
+ "typedoc": "^0.28.15",
32
+ "typedoc-plugin-rename-defaults": "^0.7.3",
30
33
  "typescript": "^5.9.3",
31
34
  "vite": "^7.2.7"
32
35
  }