@inferencesh/sdk 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +98 -8
- package/dist/agent.d.ts +75 -0
- package/dist/agent.js +196 -0
- package/dist/client.d.ts +111 -10
- package/dist/client.js +175 -13
- package/dist/client.test.js +5 -5
- package/dist/index.d.ts +3 -1
- package/dist/index.js +18 -2
- package/dist/stream.d.ts +8 -0
- package/dist/stream.js +48 -0
- package/dist/tool-builder.d.ts +82 -0
- package/dist/tool-builder.js +212 -0
- package/dist/tool-builder.test.d.ts +1 -0
- package/dist/tool-builder.test.js +291 -0
- package/dist/types.d.ts +625 -2719
- package/dist/types.js +45 -266
- package/package.json +1 -1
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Tool Builder - Fluent API for defining agent tools
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.internalTools = exports.webhookTool = exports.agentTool = exports.appTool = exports.tool = exports.optional = exports.array = exports.object = exports.enumOf = exports.boolean = exports.integer = exports.number = exports.string = void 0;
|
|
7
|
+
const types_1 = require("./types");
|
|
8
|
+
// =============================================================================
|
|
9
|
+
// Schema Builders
|
|
10
|
+
// =============================================================================
|
|
11
|
+
const string = (description) => ({ type: 'string', description });
|
|
12
|
+
exports.string = string;
|
|
13
|
+
const number = (description) => ({ type: 'number', description });
|
|
14
|
+
exports.number = number;
|
|
15
|
+
const integer = (description) => ({ type: 'integer', description });
|
|
16
|
+
exports.integer = integer;
|
|
17
|
+
const boolean = (description) => ({ type: 'boolean', description });
|
|
18
|
+
exports.boolean = boolean;
|
|
19
|
+
const enumOf = (values, description) => ({ type: 'string', enum: values, description });
|
|
20
|
+
exports.enumOf = enumOf;
|
|
21
|
+
const object = (properties, description) => ({ type: 'object', properties, description });
|
|
22
|
+
exports.object = object;
|
|
23
|
+
const array = (items, description) => ({ type: 'array', items, description });
|
|
24
|
+
exports.array = array;
|
|
25
|
+
const optional = (schema) => ({ ...schema, optional: true });
|
|
26
|
+
exports.optional = optional;
|
|
27
|
+
// =============================================================================
|
|
28
|
+
// JSON Schema Generator
|
|
29
|
+
// =============================================================================
|
|
30
|
+
function toJsonSchema(params) {
|
|
31
|
+
const properties = {};
|
|
32
|
+
const required = [];
|
|
33
|
+
for (const [key, schema] of Object.entries(params)) {
|
|
34
|
+
const prop = { type: schema.type };
|
|
35
|
+
if (schema.description)
|
|
36
|
+
prop.description = schema.description;
|
|
37
|
+
if (schema.enum)
|
|
38
|
+
prop.enum = schema.enum;
|
|
39
|
+
if (schema.properties) {
|
|
40
|
+
const nested = toJsonSchema(schema.properties);
|
|
41
|
+
prop.properties = nested.properties;
|
|
42
|
+
}
|
|
43
|
+
if (schema.items) {
|
|
44
|
+
const itemSchema = toJsonSchema({ _item: schema.items });
|
|
45
|
+
prop.items = itemSchema.properties['_item'];
|
|
46
|
+
}
|
|
47
|
+
properties[key] = prop;
|
|
48
|
+
if (!schema.optional)
|
|
49
|
+
required.push(key);
|
|
50
|
+
}
|
|
51
|
+
return { type: 'object', properties, required };
|
|
52
|
+
}
|
|
53
|
+
// =============================================================================
|
|
54
|
+
// Tool Builders
|
|
55
|
+
// =============================================================================
|
|
56
|
+
class ToolBuilder {
|
|
57
|
+
constructor(name) {
|
|
58
|
+
this.desc = '';
|
|
59
|
+
this.params = {};
|
|
60
|
+
this.approval = false;
|
|
61
|
+
this.name = name;
|
|
62
|
+
}
|
|
63
|
+
describe(description) {
|
|
64
|
+
this.desc = description;
|
|
65
|
+
return this;
|
|
66
|
+
}
|
|
67
|
+
display(name) {
|
|
68
|
+
this.displayName = name;
|
|
69
|
+
return this;
|
|
70
|
+
}
|
|
71
|
+
param(name, schema) {
|
|
72
|
+
this.params[name] = schema;
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
requireApproval() {
|
|
76
|
+
this.approval = true;
|
|
77
|
+
return this;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
class ClientToolBuilder extends ToolBuilder {
|
|
81
|
+
build() {
|
|
82
|
+
return {
|
|
83
|
+
name: this.name,
|
|
84
|
+
display_name: this.displayName || this.name,
|
|
85
|
+
description: this.desc,
|
|
86
|
+
type: types_1.ToolTypeClient,
|
|
87
|
+
require_approval: this.approval || undefined,
|
|
88
|
+
client: { input_schema: toJsonSchema(this.params) },
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
class AppToolBuilder extends ToolBuilder {
|
|
93
|
+
constructor(name, appRef) {
|
|
94
|
+
super(name);
|
|
95
|
+
this.appRef = appRef;
|
|
96
|
+
}
|
|
97
|
+
build() {
|
|
98
|
+
const [ns, rest] = this.appRef.split('/');
|
|
99
|
+
const [appName, version] = rest?.split('@') || [];
|
|
100
|
+
return {
|
|
101
|
+
name: this.name,
|
|
102
|
+
display_name: this.displayName || this.name,
|
|
103
|
+
description: this.desc,
|
|
104
|
+
type: types_1.ToolTypeApp,
|
|
105
|
+
require_approval: this.approval || undefined,
|
|
106
|
+
app: { id: `${ns}/${appName}`, version_id: version },
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
class AgentToolBuilder extends ToolBuilder {
|
|
111
|
+
constructor(name, agentRef) {
|
|
112
|
+
super(name);
|
|
113
|
+
this.agentRef = agentRef;
|
|
114
|
+
}
|
|
115
|
+
build() {
|
|
116
|
+
const [ns, rest] = this.agentRef.split('/');
|
|
117
|
+
const [agentName, version] = rest?.split('@') || [];
|
|
118
|
+
return {
|
|
119
|
+
name: this.name,
|
|
120
|
+
display_name: this.displayName || this.name,
|
|
121
|
+
description: this.desc,
|
|
122
|
+
type: types_1.ToolTypeAgent,
|
|
123
|
+
require_approval: this.approval || undefined,
|
|
124
|
+
agent: { id: `${ns}/${agentName}`, version_id: version },
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
class WebhookToolBuilder extends ToolBuilder {
|
|
129
|
+
constructor(name, url) {
|
|
130
|
+
super(name);
|
|
131
|
+
this.url = url;
|
|
132
|
+
}
|
|
133
|
+
secret(key) {
|
|
134
|
+
this.secretKey = key;
|
|
135
|
+
return this;
|
|
136
|
+
}
|
|
137
|
+
build() {
|
|
138
|
+
return {
|
|
139
|
+
name: this.name,
|
|
140
|
+
display_name: this.displayName || this.name,
|
|
141
|
+
description: this.desc,
|
|
142
|
+
type: types_1.ToolTypeHook,
|
|
143
|
+
require_approval: this.approval || undefined,
|
|
144
|
+
hook: { url: this.url, secret: this.secretKey, input_schema: toJsonSchema(this.params) },
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// =============================================================================
|
|
149
|
+
// Public API
|
|
150
|
+
// =============================================================================
|
|
151
|
+
/** Create a client tool (executed by SDK consumer) */
|
|
152
|
+
const tool = (name) => new ClientToolBuilder(name);
|
|
153
|
+
exports.tool = tool;
|
|
154
|
+
/** Create an app tool (runs another inference app) */
|
|
155
|
+
const appTool = (name, appRef) => new AppToolBuilder(name, appRef);
|
|
156
|
+
exports.appTool = appTool;
|
|
157
|
+
/** Create an agent tool (delegates to sub-agent) */
|
|
158
|
+
const agentTool = (name, agentRef) => new AgentToolBuilder(name, agentRef);
|
|
159
|
+
exports.agentTool = agentTool;
|
|
160
|
+
/** Create a webhook tool (calls external URL) */
|
|
161
|
+
const webhookTool = (name, url) => new WebhookToolBuilder(name, url);
|
|
162
|
+
exports.webhookTool = webhookTool;
|
|
163
|
+
// =============================================================================
|
|
164
|
+
// Internal Tools Builder
|
|
165
|
+
// =============================================================================
|
|
166
|
+
class InternalToolsBuilder {
|
|
167
|
+
constructor() {
|
|
168
|
+
this.config = {};
|
|
169
|
+
}
|
|
170
|
+
/** Enable plan tools (Create, Update, Load) */
|
|
171
|
+
plan(enabled = true) {
|
|
172
|
+
this.config.plan = enabled;
|
|
173
|
+
return this;
|
|
174
|
+
}
|
|
175
|
+
/** Enable memory tools (Set, Get, GetAll) */
|
|
176
|
+
memory(enabled = true) {
|
|
177
|
+
this.config.memory = enabled;
|
|
178
|
+
return this;
|
|
179
|
+
}
|
|
180
|
+
/** Enable widget tools (UI, HTML) - top-level only */
|
|
181
|
+
widget(enabled = true) {
|
|
182
|
+
this.config.widget = enabled;
|
|
183
|
+
return this;
|
|
184
|
+
}
|
|
185
|
+
/** Enable finish tool - sub-agents only */
|
|
186
|
+
finish(enabled = true) {
|
|
187
|
+
this.config.finish = enabled;
|
|
188
|
+
return this;
|
|
189
|
+
}
|
|
190
|
+
/** Enable all internal tools */
|
|
191
|
+
all() {
|
|
192
|
+
this.config.plan = true;
|
|
193
|
+
this.config.memory = true;
|
|
194
|
+
this.config.widget = true;
|
|
195
|
+
this.config.finish = true;
|
|
196
|
+
return this;
|
|
197
|
+
}
|
|
198
|
+
/** Disable all internal tools */
|
|
199
|
+
none() {
|
|
200
|
+
this.config.plan = false;
|
|
201
|
+
this.config.memory = false;
|
|
202
|
+
this.config.widget = false;
|
|
203
|
+
this.config.finish = false;
|
|
204
|
+
return this;
|
|
205
|
+
}
|
|
206
|
+
build() {
|
|
207
|
+
return this.config;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/** Create internal tools configuration */
|
|
211
|
+
const internalTools = () => new InternalToolsBuilder();
|
|
212
|
+
exports.internalTools = internalTools;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tool_builder_1 = require("./tool-builder");
|
|
4
|
+
const types_1 = require("./types");
|
|
5
|
+
describe('Schema Helpers', () => {
|
|
6
|
+
describe('string', () => {
|
|
7
|
+
it('creates string schema without description', () => {
|
|
8
|
+
const schema = (0, tool_builder_1.string)();
|
|
9
|
+
expect(schema).toEqual({ type: 'string' });
|
|
10
|
+
});
|
|
11
|
+
it('creates string schema with description', () => {
|
|
12
|
+
const schema = (0, tool_builder_1.string)('User name');
|
|
13
|
+
expect(schema).toEqual({ type: 'string', description: 'User name' });
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
describe('number', () => {
|
|
17
|
+
it('creates number schema', () => {
|
|
18
|
+
expect((0, tool_builder_1.number)()).toEqual({ type: 'number' });
|
|
19
|
+
expect((0, tool_builder_1.number)('Temperature')).toEqual({ type: 'number', description: 'Temperature' });
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
describe('integer', () => {
|
|
23
|
+
it('creates integer schema', () => {
|
|
24
|
+
expect((0, tool_builder_1.integer)()).toEqual({ type: 'integer' });
|
|
25
|
+
expect((0, tool_builder_1.integer)('Age')).toEqual({ type: 'integer', description: 'Age' });
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
describe('boolean', () => {
|
|
29
|
+
it('creates boolean schema', () => {
|
|
30
|
+
expect((0, tool_builder_1.boolean)()).toEqual({ type: 'boolean' });
|
|
31
|
+
expect((0, tool_builder_1.boolean)('Is active')).toEqual({ type: 'boolean', description: 'Is active' });
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
describe('enumOf', () => {
|
|
35
|
+
it('creates enum schema', () => {
|
|
36
|
+
const schema = (0, tool_builder_1.enumOf)(['low', 'medium', 'high']);
|
|
37
|
+
expect(schema).toEqual({ type: 'string', enum: ['low', 'medium', 'high'] });
|
|
38
|
+
});
|
|
39
|
+
it('creates enum schema with description', () => {
|
|
40
|
+
const schema = (0, tool_builder_1.enumOf)(['a', 'b'], 'Priority level');
|
|
41
|
+
expect(schema).toEqual({ type: 'string', enum: ['a', 'b'], description: 'Priority level' });
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
describe('object', () => {
|
|
45
|
+
it('creates object schema with nested properties', () => {
|
|
46
|
+
const schema = (0, tool_builder_1.object)({
|
|
47
|
+
name: (0, tool_builder_1.string)('Name'),
|
|
48
|
+
age: (0, tool_builder_1.integer)('Age'),
|
|
49
|
+
});
|
|
50
|
+
expect(schema).toEqual({
|
|
51
|
+
type: 'object',
|
|
52
|
+
properties: {
|
|
53
|
+
name: { type: 'string', description: 'Name' },
|
|
54
|
+
age: { type: 'integer', description: 'Age' },
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
it('creates object schema with description', () => {
|
|
59
|
+
const schema = (0, tool_builder_1.object)({ x: (0, tool_builder_1.number)() }, 'Coordinates');
|
|
60
|
+
expect(schema.description).toBe('Coordinates');
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
describe('array', () => {
|
|
64
|
+
it('creates array schema', () => {
|
|
65
|
+
const schema = (0, tool_builder_1.array)((0, tool_builder_1.string)('Tag'));
|
|
66
|
+
expect(schema).toEqual({
|
|
67
|
+
type: 'array',
|
|
68
|
+
items: { type: 'string', description: 'Tag' },
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
it('creates array schema with description', () => {
|
|
72
|
+
const schema = (0, tool_builder_1.array)((0, tool_builder_1.integer)(), 'List of IDs');
|
|
73
|
+
expect(schema).toEqual({
|
|
74
|
+
type: 'array',
|
|
75
|
+
items: { type: 'integer' },
|
|
76
|
+
description: 'List of IDs',
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
describe('optional', () => {
|
|
81
|
+
it('marks schema as optional', () => {
|
|
82
|
+
const schema = (0, tool_builder_1.optional)((0, tool_builder_1.string)('Optional field'));
|
|
83
|
+
expect(schema).toEqual({ type: 'string', description: 'Optional field', optional: true });
|
|
84
|
+
});
|
|
85
|
+
it('preserves original schema properties', () => {
|
|
86
|
+
const schema = (0, tool_builder_1.optional)((0, tool_builder_1.enumOf)(['a', 'b'], 'Choice'));
|
|
87
|
+
expect(schema.enum).toEqual(['a', 'b']);
|
|
88
|
+
expect(schema.optional).toBe(true);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
describe('ClientToolBuilder (tool)', () => {
|
|
93
|
+
it('creates minimal tool', () => {
|
|
94
|
+
const t = (0, tool_builder_1.tool)('my_tool').build();
|
|
95
|
+
expect(t).toEqual({
|
|
96
|
+
name: 'my_tool',
|
|
97
|
+
display_name: 'my_tool',
|
|
98
|
+
description: '',
|
|
99
|
+
type: types_1.ToolTypeClient,
|
|
100
|
+
require_approval: undefined,
|
|
101
|
+
client: {
|
|
102
|
+
input_schema: { type: 'object', properties: {}, required: [] },
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
it('creates tool with description', () => {
|
|
107
|
+
const t = (0, tool_builder_1.tool)('greet').describe('Says hello').build();
|
|
108
|
+
expect(t.description).toBe('Says hello');
|
|
109
|
+
});
|
|
110
|
+
it('creates tool with display name', () => {
|
|
111
|
+
const t = (0, tool_builder_1.tool)('get_data').display('Get Data').build();
|
|
112
|
+
expect(t.display_name).toBe('Get Data');
|
|
113
|
+
});
|
|
114
|
+
it('creates tool with parameters', () => {
|
|
115
|
+
const t = (0, tool_builder_1.tool)('add')
|
|
116
|
+
.param('a', (0, tool_builder_1.number)('First number'))
|
|
117
|
+
.param('b', (0, tool_builder_1.number)('Second number'))
|
|
118
|
+
.build();
|
|
119
|
+
expect(t.client?.input_schema).toEqual({
|
|
120
|
+
type: 'object',
|
|
121
|
+
properties: {
|
|
122
|
+
a: { type: 'number', description: 'First number' },
|
|
123
|
+
b: { type: 'number', description: 'Second number' },
|
|
124
|
+
},
|
|
125
|
+
required: ['a', 'b'],
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
it('handles optional parameters correctly', () => {
|
|
129
|
+
const t = (0, tool_builder_1.tool)('search')
|
|
130
|
+
.param('query', (0, tool_builder_1.string)('Search query'))
|
|
131
|
+
.param('limit', (0, tool_builder_1.optional)((0, tool_builder_1.integer)('Max results')))
|
|
132
|
+
.build();
|
|
133
|
+
expect(t.client?.input_schema.required).toEqual(['query']);
|
|
134
|
+
expect(t.client?.input_schema.properties).toHaveProperty('limit');
|
|
135
|
+
});
|
|
136
|
+
it('creates tool with require approval', () => {
|
|
137
|
+
const t = (0, tool_builder_1.tool)('dangerous').requireApproval().build();
|
|
138
|
+
expect(t.require_approval).toBe(true);
|
|
139
|
+
});
|
|
140
|
+
it('creates tool with nested object parameters', () => {
|
|
141
|
+
const t = (0, tool_builder_1.tool)('create_user')
|
|
142
|
+
.param('user', (0, tool_builder_1.object)({
|
|
143
|
+
name: (0, tool_builder_1.string)('Name'),
|
|
144
|
+
email: (0, tool_builder_1.string)('Email'),
|
|
145
|
+
}, 'User data'))
|
|
146
|
+
.build();
|
|
147
|
+
const schema = t.client?.input_schema;
|
|
148
|
+
expect(schema?.properties?.user).toMatchObject({
|
|
149
|
+
type: 'object',
|
|
150
|
+
properties: {
|
|
151
|
+
name: { type: 'string', description: 'Name' },
|
|
152
|
+
email: { type: 'string', description: 'Email' },
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
it('creates tool with array parameters', () => {
|
|
157
|
+
const t = (0, tool_builder_1.tool)('process_items')
|
|
158
|
+
.param('items', (0, tool_builder_1.array)((0, tool_builder_1.string)('Item'), 'List of items'))
|
|
159
|
+
.build();
|
|
160
|
+
expect(t.client?.input_schema.properties?.items).toMatchObject({
|
|
161
|
+
type: 'array',
|
|
162
|
+
items: { type: 'string', description: 'Item' },
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
describe('AppToolBuilder (appTool)', () => {
|
|
167
|
+
it('creates app tool with reference', () => {
|
|
168
|
+
const t = (0, tool_builder_1.appTool)('generate', 'infsh/flux@v1.0')
|
|
169
|
+
.describe('Generate image')
|
|
170
|
+
.build();
|
|
171
|
+
expect(t.type).toBe(types_1.ToolTypeApp);
|
|
172
|
+
expect(t.app).toEqual({ id: 'infsh/flux', version_id: 'v1.0' });
|
|
173
|
+
expect(t.description).toBe('Generate image');
|
|
174
|
+
});
|
|
175
|
+
it('handles app reference with latest version', () => {
|
|
176
|
+
const t = (0, tool_builder_1.appTool)('browse', 'my-org/browser@latest').build();
|
|
177
|
+
expect(t.app).toEqual({ id: 'my-org/browser', version_id: 'latest' });
|
|
178
|
+
});
|
|
179
|
+
it('includes parameters', () => {
|
|
180
|
+
const t = (0, tool_builder_1.appTool)('fetch', 'infsh/fetch@v1')
|
|
181
|
+
.param('url', (0, tool_builder_1.string)('URL to fetch'))
|
|
182
|
+
.build();
|
|
183
|
+
expect(t.name).toBe('fetch');
|
|
184
|
+
// Note: App tools don't use client input_schema, params are for documentation
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
describe('AgentToolBuilder (agentTool)', () => {
|
|
188
|
+
it('creates agent tool with reference', () => {
|
|
189
|
+
const t = (0, tool_builder_1.agentTool)('research', 'acme/researcher@v2')
|
|
190
|
+
.describe('Research a topic')
|
|
191
|
+
.build();
|
|
192
|
+
expect(t.type).toBe(types_1.ToolTypeAgent);
|
|
193
|
+
expect(t.agent).toEqual({ id: 'acme/researcher', version_id: 'v2' });
|
|
194
|
+
});
|
|
195
|
+
it('supports display name and approval', () => {
|
|
196
|
+
const t = (0, tool_builder_1.agentTool)('coder', 'infsh/code-agent@latest')
|
|
197
|
+
.display('Code Assistant')
|
|
198
|
+
.requireApproval()
|
|
199
|
+
.build();
|
|
200
|
+
expect(t.display_name).toBe('Code Assistant');
|
|
201
|
+
expect(t.require_approval).toBe(true);
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
describe('WebhookToolBuilder (webhookTool)', () => {
|
|
205
|
+
it('creates webhook tool with URL', () => {
|
|
206
|
+
const t = (0, tool_builder_1.webhookTool)('notify', 'https://api.example.com/webhook')
|
|
207
|
+
.describe('Send notification')
|
|
208
|
+
.build();
|
|
209
|
+
expect(t.type).toBe(types_1.ToolTypeHook);
|
|
210
|
+
expect(t.hook?.url).toBe('https://api.example.com/webhook');
|
|
211
|
+
expect(t.description).toBe('Send notification');
|
|
212
|
+
});
|
|
213
|
+
it('includes secret key', () => {
|
|
214
|
+
const t = (0, tool_builder_1.webhookTool)('slack', 'https://hooks.slack.com/services/xxx')
|
|
215
|
+
.secret('SLACK_SECRET')
|
|
216
|
+
.build();
|
|
217
|
+
expect(t.hook?.secret).toBe('SLACK_SECRET');
|
|
218
|
+
});
|
|
219
|
+
it('generates input schema for parameters', () => {
|
|
220
|
+
const t = (0, tool_builder_1.webhookTool)('send', 'https://api.example.com')
|
|
221
|
+
.param('message', (0, tool_builder_1.string)('Message'))
|
|
222
|
+
.param('priority', (0, tool_builder_1.optional)((0, tool_builder_1.enumOf)(['low', 'high'])))
|
|
223
|
+
.build();
|
|
224
|
+
expect(t.hook?.input_schema).toEqual({
|
|
225
|
+
type: 'object',
|
|
226
|
+
properties: {
|
|
227
|
+
message: { type: 'string', description: 'Message' },
|
|
228
|
+
priority: { type: 'string', enum: ['low', 'high'] },
|
|
229
|
+
},
|
|
230
|
+
required: ['message'],
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
describe('InternalToolsBuilder (internalTools)', () => {
|
|
235
|
+
it('creates empty config by default', () => {
|
|
236
|
+
const config = (0, tool_builder_1.internalTools)().build();
|
|
237
|
+
expect(config).toEqual({});
|
|
238
|
+
});
|
|
239
|
+
it('enables plan tools', () => {
|
|
240
|
+
const config = (0, tool_builder_1.internalTools)().plan().build();
|
|
241
|
+
expect(config).toEqual({ plan: true });
|
|
242
|
+
});
|
|
243
|
+
it('enables memory tools', () => {
|
|
244
|
+
const config = (0, tool_builder_1.internalTools)().memory().build();
|
|
245
|
+
expect(config).toEqual({ memory: true });
|
|
246
|
+
});
|
|
247
|
+
it('enables widget tools', () => {
|
|
248
|
+
const config = (0, tool_builder_1.internalTools)().widget().build();
|
|
249
|
+
expect(config).toEqual({ widget: true });
|
|
250
|
+
});
|
|
251
|
+
it('enables finish tool', () => {
|
|
252
|
+
const config = (0, tool_builder_1.internalTools)().finish().build();
|
|
253
|
+
expect(config).toEqual({ finish: true });
|
|
254
|
+
});
|
|
255
|
+
it('chains multiple tool enables', () => {
|
|
256
|
+
const config = (0, tool_builder_1.internalTools)().plan().memory().widget().build();
|
|
257
|
+
expect(config).toEqual({ plan: true, memory: true, widget: true });
|
|
258
|
+
});
|
|
259
|
+
it('enables all tools with all()', () => {
|
|
260
|
+
const config = (0, tool_builder_1.internalTools)().all().build();
|
|
261
|
+
expect(config).toEqual({ plan: true, memory: true, widget: true, finish: true });
|
|
262
|
+
});
|
|
263
|
+
it('disables all tools with none()', () => {
|
|
264
|
+
const config = (0, tool_builder_1.internalTools)().none().build();
|
|
265
|
+
expect(config).toEqual({ plan: false, memory: false, widget: false, finish: false });
|
|
266
|
+
});
|
|
267
|
+
it('allows explicit disable', () => {
|
|
268
|
+
const config = (0, tool_builder_1.internalTools)().plan(false).memory(true).build();
|
|
269
|
+
expect(config).toEqual({ plan: false, memory: true });
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
describe('Fluent API chaining', () => {
|
|
273
|
+
it('supports full fluent chain', () => {
|
|
274
|
+
const t = (0, tool_builder_1.tool)('complex')
|
|
275
|
+
.display('Complex Tool')
|
|
276
|
+
.describe('A complex tool with many params')
|
|
277
|
+
.param('name', (0, tool_builder_1.string)('Name'))
|
|
278
|
+
.param('count', (0, tool_builder_1.integer)('Count'))
|
|
279
|
+
.param('options', (0, tool_builder_1.optional)((0, tool_builder_1.object)({
|
|
280
|
+
verbose: (0, tool_builder_1.boolean)('Verbose mode'),
|
|
281
|
+
tags: (0, tool_builder_1.array)((0, tool_builder_1.string)('Tag')),
|
|
282
|
+
})))
|
|
283
|
+
.requireApproval()
|
|
284
|
+
.build();
|
|
285
|
+
expect(t.name).toBe('complex');
|
|
286
|
+
expect(t.display_name).toBe('Complex Tool');
|
|
287
|
+
expect(t.description).toBe('A complex tool with many params');
|
|
288
|
+
expect(t.require_approval).toBe(true);
|
|
289
|
+
expect(t.client?.input_schema.required).toEqual(['name', 'count']);
|
|
290
|
+
});
|
|
291
|
+
});
|