@atgs/tapeworm 0.1.5 → 0.1.7
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/README.md +45 -35
- package/dist/agent/agent.d.ts +3 -1
- package/dist/tapeworm.cjs.js +1 -1
- package/dist/tapeworm.es.js +63 -61
- package/dist/tapeworm.umd.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|

|
|
2
2
|
|
|
3
|
-
# Tapeworm
|
|
3
|
+
# Tapeworm Core
|
|
4
4
|
|
|
5
|
-
<h3>In-browser and Node
|
|
5
|
+
<h3>In-browser and Node Agent Framework.</h3>
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.org/package/@atgs/tapeworm.svg)
|
|
8
|
-
|
|
9
8
|
[](https://npm-stat.com/charts.html?package=@atgs/tapeworm)
|
|
10
|
-
|
|
11
9
|
[repo link](https://github.com/andygrace227/tapeworm)
|
|
12
10
|
|
|
13
11
|
This is the root package for Tapeworm. You can consume other packages like @atgs/tapeworm_bedrock for AWS Bedrock support.
|
|
@@ -18,13 +16,22 @@ It provides an object-oriented API to create agents that run either on Node or w
|
|
|
18
16
|
|
|
19
17
|
## Current Features
|
|
20
18
|
|
|
21
|
-
- Base API Defined.
|
|
22
19
|
- Supports `function` tools.
|
|
23
20
|
- Supports Ollama models.
|
|
24
|
-
- Has a Babel plugin to make tool creation
|
|
21
|
+
- Has a Babel plugin to make tool creation easy.
|
|
22
|
+
- Has TS decorators to make tool creation really easy, too!
|
|
23
|
+
- Supports browser and Node.
|
|
24
|
+
|
|
25
|
+
## Tapeworm's Tenets
|
|
26
|
+
|
|
27
|
+
- **Be the most ergonomic agentic solution for Node and the browser.** Each commit should make it easier to develop and deploy agentic AI solutions.
|
|
28
|
+
- **Be as model-agnostic as possible.** Use your own machine, AWS, Google, a literal potato... we don't care.
|
|
29
|
+
- **Keep things light.** We already waste so much water and energy with AI. The overhead from Tapeworm should be kept to a minimum when possible.
|
|
25
30
|
|
|
26
31
|
## Examples
|
|
27
32
|
|
|
33
|
+
### How do I define a tool?
|
|
34
|
+
|
|
28
35
|
#### With the babel plugin (@atgs/@atgs/babel-plugin-tapeworm-decorator) (recommended, super concise)
|
|
29
36
|
|
|
30
37
|
```js
|
|
@@ -50,22 +57,37 @@ class AdditionTool extends Tool {
|
|
|
50
57
|
return a + b;
|
|
51
58
|
}
|
|
52
59
|
}
|
|
60
|
+
```
|
|
53
61
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
62
|
+
#### With Typescript Decorators
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
@ToolName("AdditionTool")
|
|
66
|
+
@ToolDescription("Adds two numbers together.")
|
|
67
|
+
@ToolParameter({
|
|
68
|
+
name: "a",
|
|
69
|
+
description: "The first number to add",
|
|
70
|
+
required: true,
|
|
71
|
+
type: "number",
|
|
72
|
+
})
|
|
73
|
+
@ToolParameter({
|
|
74
|
+
name: "b",
|
|
75
|
+
description: "The second number to add",
|
|
76
|
+
required: true,
|
|
77
|
+
type: "number",
|
|
78
|
+
})
|
|
79
|
+
@ToolOutput("The sum of inputs a and b")
|
|
80
|
+
class AdditionTool extends Tool {
|
|
81
|
+
execute(input: any) {
|
|
82
|
+
let a = +input.a;
|
|
83
|
+
let b = +input.b;
|
|
84
|
+
console.log("Adding " + a + " and " + b + ": " + (a + b));
|
|
85
|
+
return a + b;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
66
88
|
```
|
|
67
89
|
|
|
68
|
-
#### Without the plugin (still pretty readable
|
|
90
|
+
#### Without the plugin (still pretty readable)
|
|
69
91
|
|
|
70
92
|
```js
|
|
71
93
|
import {
|
|
@@ -77,18 +99,10 @@ import {
|
|
|
77
99
|
} from "../../dist/tapeworm.es.js";
|
|
78
100
|
|
|
79
101
|
class AdditionTool extends Tool {
|
|
80
|
-
/**
|
|
81
|
-
* Unique name used to reference this tool.
|
|
82
|
-
* @returns Tool identifier string.
|
|
83
|
-
*/
|
|
84
102
|
getName() {
|
|
85
103
|
return "AdditionTool";
|
|
86
104
|
}
|
|
87
105
|
|
|
88
|
-
/**
|
|
89
|
-
* Short description provided to the model.
|
|
90
|
-
* @returns Human-readable explanation of the tool.
|
|
91
|
-
*/
|
|
92
106
|
getDescription() {
|
|
93
107
|
return "Adds two numbers together.";
|
|
94
108
|
}
|
|
@@ -117,9 +131,11 @@ class AdditionTool extends Tool {
|
|
|
117
131
|
return a + b;
|
|
118
132
|
}
|
|
119
133
|
}
|
|
134
|
+
```
|
|
120
135
|
|
|
121
|
-
|
|
136
|
+
#### Then calling the agent:
|
|
122
137
|
|
|
138
|
+
```js
|
|
123
139
|
const ollama = new OllamaModel("http://localhost:11434", "gpt-oss:20b", {
|
|
124
140
|
stream: false,
|
|
125
141
|
});
|
|
@@ -131,15 +147,9 @@ const agent = Agent.builder()
|
|
|
131
147
|
.model(ollama)
|
|
132
148
|
.build();
|
|
133
149
|
|
|
134
|
-
await agent.invoke("What is 9 + 10");
|
|
150
|
+
await agent.invoke("What is 9 + 10?");
|
|
135
151
|
```
|
|
136
152
|
|
|
137
|
-
## Tapeworm's Tenets
|
|
138
|
-
|
|
139
|
-
- **Be the most ergonomic agentic solution for Node and the browser.** Each commit should make it easier to develop and deploy agentic AI solutions.
|
|
140
|
-
- **Be as model-agnostic as possible.** Use your own machine, AWS, Google, a literal potato... we don't care.
|
|
141
|
-
- **Keep things light.** We already waste so much water and energy with AI. The overhead from Tapeworm should be kept to a minimum when possible.
|
|
142
|
-
|
|
143
153
|
## Roadmap
|
|
144
154
|
|
|
145
155
|
Tapeworm seeks to be the most ergonomic agentic solution for Node and the browser.
|
package/dist/agent/agent.d.ts
CHANGED
|
@@ -19,9 +19,11 @@ export default class Agent {
|
|
|
19
19
|
/**
|
|
20
20
|
* Run the full agent loop for a user query: seed the conversation, invoke the model,
|
|
21
21
|
* and execute any returned tool calls until completion.
|
|
22
|
+
* *
|
|
22
23
|
* @param query User-provided input to hand to the agent.
|
|
24
|
+
* @param callback A function that handles the messages coming from the agent.
|
|
23
25
|
*/
|
|
24
|
-
invoke(query: string): Promise<void>;
|
|
26
|
+
invoke(query: string, callback?: (m: Message) => void): Promise<void>;
|
|
25
27
|
/**
|
|
26
28
|
* Ask the backing model for the next response given the current conversation state.
|
|
27
29
|
* @returns Parsed model response including content, thinking, and tool calls.
|
package/dist/tapeworm.cjs.js
CHANGED
|
@@ -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,o){this.role=e,this.content=o}static builder(){return new b}filter(e){return this.content.filter(o=>o.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 o of e)this._content.push(o);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 a={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 a.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 a.Thinking}get(){return this.thought}static of(e){return new this(e)}}class c extends m{id;toolName;toolResult;constructor(e,o,s){super(),this.id=e,this.toolName=o,this.toolResult=s}getMessageComponentType(){return a.ToolResult}static of(e,o){return new this(e.id,e.name,o)}}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,o){this.messages=e,this.tools=o}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 a.ToolCall}constructor(e,o,s,n,r){super(),this.sequence=e,this.name=o,this.parameters=s,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,o,s,n,r){this.name=e,this.model=s,this.conversationManager=n,this.tools=o,this.callback=r,this.conversationManager.configure(s)}async invoke(e){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 s=await this._runQuery();this.callback(s),this.conversation.append(s),o=!0;const n=s.filter(a.ToolCall);if(n!=null&&n.length!=0){o=!1,n.sort((r,l)=>(r.sequence??0)<(l.sequence??0)?-1:1);for(let r of n)await this._runTool(r)}}}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 o=this.tools[this.toolNameToIndexMap[e.name]];try{let s=await o.execute(e.parameters);this.conversation.append(u.builder().role("tool").toolResult(c.of(e,s)).build())}catch(s){this.conversation.append(u.builder().role("tool").toolResult(c.of(e,JSON.stringify(s))).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(a.Thinking))console.log("\x1B[90m"+e.get()+"\x1B[0m");for(const e of t.filter(a.Content))console.log(e.get());for(const e of t.filter(a.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,o){this.parameters=e,this.output=o}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,o,s,n){this.name=e,this.description=o,this.type=s,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,o,s){super(),this.endpoint=e,this.model=o,this.options=s}async invoke(e){let o={model:this.model,messages:this._formatMessages(e),tools:this._formatTools(e),...this.options},s=await fetch(this.endpoint+"/api/chat",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(o)});if(!s.ok)throw new Error(`HTTP error! status: ${s.status}`);let n=await s.json(),r=[];if(n.message.tool_calls)for(let l in n.message.tool_calls){const i=n.message.tool_calls[l];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 o=[];for(let s of e.tools){let n={},r=[];for(let i of s.getToolSchema().parameters)n[i.name]={},n[i.name].type=i.type,n[i.name].description=i.description,i.required&&r.push(i.name);let l={type:"function",function:{name:s.getName(),description:s.getDescription(),parameters:{type:"object",properties:n,required:r}}};o.push(l)}return o}_formatMessages(e){let o=[];for(let s of e.messages){if(s.role=="assistant"||s.role=="system"||s.role=="user"){o.push(this._formatSingleMessage(s));continue}if(s.role=="tool"){for(const n of s.content)if(n.getMessageComponentType()==a.ToolResult){const r=n;o.push({role:s.role,name:r.toolName,content:JSON.stringify(r.toolResult)})}}}return o}_formatSingleMessage(e){let o={role:e.role},s,n,r;for(const l of e.content){if(l.getMessageComponentType()==a.Content){const i=l;s==null&&(s=""),s+=i.get()}if(l.getMessageComponentType()==a.Thinking){const i=l;r==null&&(r=""),r+=i.get()}if(l.getMessageComponentType()==a.ToolCall){const i=l;n==null&&(n=[]),n.push(this._formatToolCall(i))}}return s!=null&&(o.content=s),n!=null&&(o.tool_calls=n),r!=null&&(o.thinking=r),o}_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,"getName",{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=a;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 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;
|
package/dist/tapeworm.es.js
CHANGED
|
@@ -62,8 +62,8 @@ class h {
|
|
|
62
62
|
* @param role Source of the message (e.g., user, assistant, tool).
|
|
63
63
|
* @param content Ordered list of message components that make up the message body.
|
|
64
64
|
*/
|
|
65
|
-
constructor(e,
|
|
66
|
-
this.role = e, this.content =
|
|
65
|
+
constructor(e, s) {
|
|
66
|
+
this.role = e, this.content = s;
|
|
67
67
|
}
|
|
68
68
|
/**
|
|
69
69
|
* Create a new message builder for ergonomic construction.
|
|
@@ -76,7 +76,7 @@ class h {
|
|
|
76
76
|
* Filters the message contents based on the message type.
|
|
77
77
|
*/
|
|
78
78
|
filter(e) {
|
|
79
|
-
return this.content.filter((
|
|
79
|
+
return this.content.filter((s) => s.getMessageComponentType() == e);
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
class k {
|
|
@@ -113,8 +113,8 @@ class k {
|
|
|
113
113
|
if (e == null)
|
|
114
114
|
return this;
|
|
115
115
|
this.init();
|
|
116
|
-
for (const
|
|
117
|
-
this._content.push(
|
|
116
|
+
for (const s of e)
|
|
117
|
+
this._content.push(s);
|
|
118
118
|
return this;
|
|
119
119
|
}
|
|
120
120
|
/**
|
|
@@ -241,8 +241,8 @@ class m extends c {
|
|
|
241
241
|
* @param toolName Name of the tool that produced the result.
|
|
242
242
|
* @param toolResult Output returned by the tool.
|
|
243
243
|
*/
|
|
244
|
-
constructor(e,
|
|
245
|
-
super(), this.id = e, this.toolName =
|
|
244
|
+
constructor(e, s, o) {
|
|
245
|
+
super(), this.id = e, this.toolName = s, this.toolResult = o;
|
|
246
246
|
}
|
|
247
247
|
/**
|
|
248
248
|
* Get the type of this message component, as defined in MessageComponentType.
|
|
@@ -257,8 +257,8 @@ class m extends c {
|
|
|
257
257
|
* @param toolResult Output to attach to the tool result component.
|
|
258
258
|
* @returns a new ToolResult component mirroring the provided tool call.
|
|
259
259
|
*/
|
|
260
|
-
static of(e,
|
|
261
|
-
return new this(e.id, e.name,
|
|
260
|
+
static of(e, s) {
|
|
261
|
+
return new this(e.id, e.name, s);
|
|
262
262
|
}
|
|
263
263
|
}
|
|
264
264
|
class O {
|
|
@@ -288,8 +288,8 @@ class E {
|
|
|
288
288
|
* @param messages Conversation history to send to the model.
|
|
289
289
|
* @param tools Tool definitions available for function calling.
|
|
290
290
|
*/
|
|
291
|
-
constructor(e,
|
|
292
|
-
this.messages = e, this.tools =
|
|
291
|
+
constructor(e, s) {
|
|
292
|
+
this.messages = e, this.tools = s;
|
|
293
293
|
}
|
|
294
294
|
/**
|
|
295
295
|
* Create a builder for composing a model request.
|
|
@@ -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,
|
|
363
|
-
super(), this.sequence = e, this.name =
|
|
362
|
+
constructor(e, s, o, n, r) {
|
|
363
|
+
super(), this.sequence = e, this.name = s, this.parameters = o, this.type = n, this.id = r;
|
|
364
364
|
}
|
|
365
365
|
/**
|
|
366
366
|
* Convenience factory for a ToolCallBuilder.
|
|
@@ -444,15 +444,17 @@ class j {
|
|
|
444
444
|
conversationManager;
|
|
445
445
|
toolNameToIndexMap;
|
|
446
446
|
callback;
|
|
447
|
-
constructor(e,
|
|
448
|
-
this.name = e, this.model =
|
|
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);
|
|
449
449
|
}
|
|
450
450
|
/**
|
|
451
451
|
* Run the full agent loop for a user query: seed the conversation, invoke the model,
|
|
452
452
|
* and execute any returned tool calls until completion.
|
|
453
|
+
* *
|
|
453
454
|
* @param query User-provided input to hand to the agent.
|
|
455
|
+
* @param callback A function that handles the messages coming from the agent.
|
|
454
456
|
*/
|
|
455
|
-
async invoke(e) {
|
|
457
|
+
async invoke(e, s = this.callback) {
|
|
456
458
|
this.conversation == null && (this.conversation = new x(), this.conversationManager != null && (this.conversation.manager = this.conversationManager), this.systemPrompt != null && this.conversation.append(
|
|
457
459
|
h.builder().role("system").content(this.systemPrompt).build()
|
|
458
460
|
)), this.conversation.append(
|
|
@@ -460,15 +462,15 @@ class j {
|
|
|
460
462
|
);
|
|
461
463
|
let o = !1;
|
|
462
464
|
for (; !o; ) {
|
|
463
|
-
let
|
|
464
|
-
|
|
465
|
-
const
|
|
465
|
+
let n = await this._runQuery();
|
|
466
|
+
s(n), this.conversation.append(n), o = !0;
|
|
467
|
+
const r = n.filter(
|
|
466
468
|
l.ToolCall
|
|
467
469
|
);
|
|
468
|
-
if (
|
|
469
|
-
o = !1,
|
|
470
|
-
for (let
|
|
471
|
-
await this._runTool(
|
|
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)
|
|
473
|
+
await this._runTool(a);
|
|
472
474
|
}
|
|
473
475
|
}
|
|
474
476
|
}
|
|
@@ -500,15 +502,15 @@ class j {
|
|
|
500
502
|
);
|
|
501
503
|
return;
|
|
502
504
|
}
|
|
503
|
-
let
|
|
505
|
+
let s = this.tools[this.toolNameToIndexMap[e.name]];
|
|
504
506
|
try {
|
|
505
|
-
let
|
|
507
|
+
let o = await s.execute(e.parameters);
|
|
506
508
|
this.conversation.append(
|
|
507
|
-
h.builder().role("tool").toolResult(m.of(e,
|
|
509
|
+
h.builder().role("tool").toolResult(m.of(e, o)).build()
|
|
508
510
|
);
|
|
509
|
-
} catch (
|
|
511
|
+
} catch (o) {
|
|
510
512
|
this.conversation.append(
|
|
511
|
-
h.builder().role("tool").toolResult(m.of(e, JSON.stringify(
|
|
513
|
+
h.builder().role("tool").toolResult(m.of(e, JSON.stringify(o))).build()
|
|
512
514
|
);
|
|
513
515
|
}
|
|
514
516
|
}
|
|
@@ -629,8 +631,8 @@ class d {
|
|
|
629
631
|
* @param parameters Ordered list of input parameters the tool accepts.
|
|
630
632
|
* @param output Human-readable description of the tool output.
|
|
631
633
|
*/
|
|
632
|
-
constructor(e,
|
|
633
|
-
this.parameters = e, this.output =
|
|
634
|
+
constructor(e, s) {
|
|
635
|
+
this.parameters = e, this.output = s;
|
|
634
636
|
}
|
|
635
637
|
/**
|
|
636
638
|
* Return a tool schema builder, so you can properly construct tools instead of dealing with the constructor
|
|
@@ -679,8 +681,8 @@ class T {
|
|
|
679
681
|
* @param type JSON-serializable type name (e.g., string, number).
|
|
680
682
|
* @param required Whether the parameter must be provided.
|
|
681
683
|
*/
|
|
682
|
-
constructor(e,
|
|
683
|
-
this.name = e, this.description =
|
|
684
|
+
constructor(e, s, o, n) {
|
|
685
|
+
this.name = e, this.description = s, this.type = o, this.required = n, this.assertValidType();
|
|
684
686
|
}
|
|
685
687
|
/**
|
|
686
688
|
* Placeholder for validating supported parameter types.
|
|
@@ -751,29 +753,29 @@ class L extends O {
|
|
|
751
753
|
* @param model Model name/tag to use for inference.
|
|
752
754
|
* @param options Additional Ollama options passed through to the API.
|
|
753
755
|
*/
|
|
754
|
-
constructor(e,
|
|
755
|
-
super(), this.endpoint = e, this.model =
|
|
756
|
+
constructor(e, s, o) {
|
|
757
|
+
super(), this.endpoint = e, this.model = s, this.options = o;
|
|
756
758
|
}
|
|
757
759
|
/**
|
|
758
760
|
* Call the Ollama chat API with the provided conversation and tools.
|
|
759
761
|
* Formats the request, performs the HTTP POST, and translates the response into a ModelResponse.
|
|
760
762
|
*/
|
|
761
763
|
async invoke(e) {
|
|
762
|
-
let
|
|
764
|
+
let s = {
|
|
763
765
|
model: this.model,
|
|
764
766
|
messages: this._formatMessages(e),
|
|
765
767
|
tools: this._formatTools(e),
|
|
766
768
|
...this.options
|
|
767
|
-
},
|
|
769
|
+
}, o = await fetch(this.endpoint + "/api/chat", {
|
|
768
770
|
method: "POST",
|
|
769
771
|
headers: {
|
|
770
772
|
"Content-Type": "application/json"
|
|
771
773
|
},
|
|
772
|
-
body: JSON.stringify(
|
|
774
|
+
body: JSON.stringify(s)
|
|
773
775
|
});
|
|
774
|
-
if (!
|
|
775
|
-
throw new Error(`HTTP error! status: ${
|
|
776
|
-
let n = await
|
|
776
|
+
if (!o.ok)
|
|
777
|
+
throw new Error(`HTTP error! status: ${o.status}`);
|
|
778
|
+
let n = await o.json(), r = [];
|
|
777
779
|
if (n.message.tool_calls)
|
|
778
780
|
for (let a in n.message.tool_calls) {
|
|
779
781
|
const i = n.message.tool_calls[a];
|
|
@@ -790,16 +792,16 @@ class L extends O {
|
|
|
790
792
|
* @returns Array of tool schema objects formatted for the Ollama API.
|
|
791
793
|
*/
|
|
792
794
|
_formatTools(e) {
|
|
793
|
-
let
|
|
794
|
-
for (let
|
|
795
|
+
let s = [];
|
|
796
|
+
for (let o of e.tools) {
|
|
795
797
|
let n = {}, r = [];
|
|
796
|
-
for (let i of
|
|
798
|
+
for (let i of o.getToolSchema().parameters)
|
|
797
799
|
n[i.name] = {}, n[i.name].type = i.type, n[i.name].description = i.description, i.required && r.push(i.name);
|
|
798
800
|
let a = {
|
|
799
801
|
type: "function",
|
|
800
802
|
function: {
|
|
801
|
-
name:
|
|
802
|
-
description:
|
|
803
|
+
name: o.getName(),
|
|
804
|
+
description: o.getDescription(),
|
|
803
805
|
parameters: {
|
|
804
806
|
type: "object",
|
|
805
807
|
properties: n,
|
|
@@ -807,9 +809,9 @@ class L extends O {
|
|
|
807
809
|
}
|
|
808
810
|
}
|
|
809
811
|
};
|
|
810
|
-
|
|
812
|
+
s.push(a);
|
|
811
813
|
}
|
|
812
|
-
return
|
|
814
|
+
return s;
|
|
813
815
|
}
|
|
814
816
|
/**
|
|
815
817
|
* Convert internal message objects into Ollama's chat message shape.
|
|
@@ -818,25 +820,25 @@ class L extends O {
|
|
|
818
820
|
* @returns Array of serialized messages ready for Ollama.
|
|
819
821
|
*/
|
|
820
822
|
_formatMessages(e) {
|
|
821
|
-
let
|
|
822
|
-
for (let
|
|
823
|
-
if (
|
|
824
|
-
|
|
823
|
+
let s = [];
|
|
824
|
+
for (let o of e.messages) {
|
|
825
|
+
if (o.role == "assistant" || o.role == "system" || o.role == "user") {
|
|
826
|
+
s.push(this._formatSingleMessage(o));
|
|
825
827
|
continue;
|
|
826
828
|
}
|
|
827
|
-
if (
|
|
828
|
-
for (const n of
|
|
829
|
+
if (o.role == "tool") {
|
|
830
|
+
for (const n of o.content)
|
|
829
831
|
if (n.getMessageComponentType() == l.ToolResult) {
|
|
830
832
|
const r = n;
|
|
831
|
-
|
|
832
|
-
role:
|
|
833
|
+
s.push({
|
|
834
|
+
role: o.role,
|
|
833
835
|
name: r.toolName,
|
|
834
836
|
content: JSON.stringify(r.toolResult)
|
|
835
837
|
});
|
|
836
838
|
}
|
|
837
839
|
}
|
|
838
840
|
}
|
|
839
|
-
return
|
|
841
|
+
return s;
|
|
840
842
|
}
|
|
841
843
|
/**
|
|
842
844
|
* Format everything sent by a user or LLM (no tools)
|
|
@@ -844,13 +846,13 @@ class L extends O {
|
|
|
844
846
|
* @returns Serialized message payload.
|
|
845
847
|
*/
|
|
846
848
|
_formatSingleMessage(e) {
|
|
847
|
-
let
|
|
849
|
+
let s = {
|
|
848
850
|
role: e.role
|
|
849
|
-
},
|
|
851
|
+
}, o, n, r;
|
|
850
852
|
for (const a of e.content) {
|
|
851
853
|
if (a.getMessageComponentType() == l.Content) {
|
|
852
854
|
const i = a;
|
|
853
|
-
|
|
855
|
+
o == null && (o = ""), o += i.get();
|
|
854
856
|
}
|
|
855
857
|
if (a.getMessageComponentType() == l.Thinking) {
|
|
856
858
|
const i = a;
|
|
@@ -861,7 +863,7 @@ class L extends O {
|
|
|
861
863
|
n == null && (n = []), n.push(this._formatToolCall(i));
|
|
862
864
|
}
|
|
863
865
|
}
|
|
864
|
-
return
|
|
866
|
+
return o != null && (s.content = o), n != null && (s.tool_calls = n), r != null && (s.thinking = r), s;
|
|
865
867
|
}
|
|
866
868
|
/**
|
|
867
869
|
* Convert a ToolCall into the structure Ollama expects.
|
|
@@ -884,7 +886,7 @@ function Q(t) {
|
|
|
884
886
|
}
|
|
885
887
|
function V(t) {
|
|
886
888
|
return (e) => {
|
|
887
|
-
Object.defineProperty(e.prototype, "
|
|
889
|
+
Object.defineProperty(e.prototype, "getDescription", {
|
|
888
890
|
value: function() {
|
|
889
891
|
return t;
|
|
890
892
|
},
|
package/dist/tapeworm.umd.js
CHANGED
|
@@ -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,o){this.role=e,this.content=o}static builder(){return new b}filter(e){return this.content.filter(o=>o.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 o of e)this._content.push(o);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 l={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 l.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 l.Thinking}get(){return this.thought}static of(e){return new this(e)}}class d extends p{id;toolName;toolResult;constructor(e,o,s){super(),this.id=e,this.toolName=o,this.toolResult=s}getMessageComponentType(){return l.ToolResult}static of(e,o){return new this(e.id,e.name,o)}}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,o){this.messages=e,this.tools=o}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 l.ToolCall}constructor(e,o,s,r,i){super(),this.sequence=e,this.name=o,this.parameters=s,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,o,s,r,i){this.name=e,this.model=s,this.conversationManager=r,this.tools=o,this.callback=i,this.conversationManager.configure(s)}async invoke(e){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 s=await this._runQuery();this.callback(s),this.conversation.append(s),o=!0;const r=s.filter(l.ToolCall);if(r!=null&&r.length!=0){o=!1,r.sort((i,u)=>(i.sequence??0)<(u.sequence??0)?-1:1);for(let i of r)await this._runTool(i)}}}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 o=this.tools[this.toolNameToIndexMap[e.name]];try{let s=await o.execute(e.parameters);this.conversation.append(h.builder().role("tool").toolResult(d.of(e,s)).build())}catch(s){this.conversation.append(h.builder().role("tool").toolResult(d.of(e,JSON.stringify(s))).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(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 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,o){this.parameters=e,this.output=o}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,o,s,r){this.name=e,this.description=o,this.type=s,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,o,s){super(),this.endpoint=e,this.model=o,this.options=s}async invoke(e){let o={model:this.model,messages:this._formatMessages(e),tools:this._formatTools(e),...this.options},s=await fetch(this.endpoint+"/api/chat",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(o)});if(!s.ok)throw new Error(`HTTP error! status: ${s.status}`);let r=await s.json(),i=[];if(r.message.tool_calls)for(let u in r.message.tool_calls){const a=r.message.tool_calls[u];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 o=[];for(let s of e.tools){let r={},i=[];for(let a of s.getToolSchema().parameters)r[a.name]={},r[a.name].type=a.type,r[a.name].description=a.description,a.required&&i.push(a.name);let u={type:"function",function:{name:s.getName(),description:s.getDescription(),parameters:{type:"object",properties:r,required:i}}};o.push(u)}return o}_formatMessages(e){let o=[];for(let s of e.messages){if(s.role=="assistant"||s.role=="system"||s.role=="user"){o.push(this._formatSingleMessage(s));continue}if(s.role=="tool"){for(const r of s.content)if(r.getMessageComponentType()==l.ToolResult){const i=r;o.push({role:s.role,name:i.toolName,content:JSON.stringify(i.toolResult)})}}}return o}_formatSingleMessage(e){let o={role:e.role},s,r,i;for(const u of e.content){if(u.getMessageComponentType()==l.Content){const a=u;s==null&&(s=""),s+=a.get()}if(u.getMessageComponentType()==l.Thinking){const a=u;i==null&&(i=""),i+=a.get()}if(u.getMessageComponentType()==l.ToolCall){const a=u;r==null&&(r=[]),r.push(this._formatToolCall(a))}}return s!=null&&(o.content=s),r!=null&&(o.tool_calls=r),i!=null&&(o.thinking=i),o}_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,"getName",{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=l,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(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"})}));
|