@tabbybyte/kimten 0.1.1 → 0.1.2
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 +21 -2
- package/lib/tools.js +41 -7
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -145,7 +145,10 @@ Create a new cat.
|
|
|
145
145
|
|
|
146
146
|
### Optional (extra whiskers)
|
|
147
147
|
|
|
148
|
-
* `toys` → object map of
|
|
148
|
+
* `toys` → object map of tool definitions. Each entry can be:
|
|
149
|
+
* async function shorthand: `async (args) => result`
|
|
150
|
+
* object form: `{ inputSchema?, description?, strict?, execute }`
|
|
151
|
+
default: `{}`
|
|
149
152
|
* `personality` → system prompt / behavior description (default: `"You are a helpful assistant."`)
|
|
150
153
|
* `hops` → max agent loop steps (default: `10`)
|
|
151
154
|
prevents infinite zoomies 🌀
|
|
@@ -194,7 +197,7 @@ Refer to https://ai-sdk.dev/docs/foundations/providers-and-models
|
|
|
194
197
|
|
|
195
198
|
### Add tools freely
|
|
196
199
|
|
|
197
|
-
Tools
|
|
200
|
+
Tools can stay simple:
|
|
198
201
|
|
|
199
202
|
```js
|
|
200
203
|
toys: {
|
|
@@ -207,6 +210,22 @@ toys: {
|
|
|
207
210
|
|
|
208
211
|
The model decides when to use them.
|
|
209
212
|
|
|
213
|
+
For stronger arg validation and better tool selection, use object form:
|
|
214
|
+
|
|
215
|
+
```js
|
|
216
|
+
import { z } from 'zod';
|
|
217
|
+
|
|
218
|
+
toys: {
|
|
219
|
+
add: {
|
|
220
|
+
description: 'Add two numbers.',
|
|
221
|
+
inputSchema: z.object({ a: z.number(), b: z.number() }),
|
|
222
|
+
async execute({ a, b }) {
|
|
223
|
+
return a + b;
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
210
229
|
### Structured output = sanity
|
|
211
230
|
|
|
212
231
|
Use Zod schemas whenever possible.
|
package/lib/tools.js
CHANGED
|
@@ -16,21 +16,21 @@ export function normalizeToys(toys) {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
if (!isPlainObject(toys)) {
|
|
19
|
-
throw new TypeError('Kimten config "toys" must be an object map of functions.');
|
|
19
|
+
throw new TypeError('Kimten config "toys" must be an object map of functions or tool definitions.');
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
const wrapped = {};
|
|
23
23
|
|
|
24
|
-
for (const [name,
|
|
25
|
-
|
|
26
|
-
throw new TypeError(`Kimten tool "${name}" must be a function.`);
|
|
27
|
-
}
|
|
24
|
+
for (const [name, entry] of Object.entries(toys)) {
|
|
25
|
+
const definition = normalizeToyDefinition(name, entry);
|
|
28
26
|
|
|
29
27
|
wrapped[name] = tool({
|
|
30
|
-
inputSchema:
|
|
28
|
+
inputSchema: definition.inputSchema,
|
|
29
|
+
...(definition.description ? { description: definition.description } : {}),
|
|
30
|
+
...(definition.strict !== undefined ? { strict: definition.strict } : {}),
|
|
31
31
|
async execute(args) {
|
|
32
32
|
try {
|
|
33
|
-
const result = await
|
|
33
|
+
const result = await definition.execute(args);
|
|
34
34
|
return toJsonSafe(result);
|
|
35
35
|
} catch (error) {
|
|
36
36
|
return {
|
|
@@ -45,6 +45,40 @@ export function normalizeToys(toys) {
|
|
|
45
45
|
return wrapped;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
function normalizeToyDefinition(name, entry) {
|
|
49
|
+
if (typeof entry === 'function') {
|
|
50
|
+
return {
|
|
51
|
+
inputSchema: z.any(),
|
|
52
|
+
execute: entry,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (!isPlainObject(entry)) {
|
|
57
|
+
throw new TypeError(
|
|
58
|
+
`Kimten tool "${name}" must be a function or an object with execute(args).`
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (typeof entry.execute !== 'function') {
|
|
63
|
+
throw new TypeError(`Kimten tool "${name}" object form must include execute(args).`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (entry.description !== undefined && typeof entry.description !== 'string') {
|
|
67
|
+
throw new TypeError(`Kimten tool "${name}" description must be a string when provided.`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (entry.strict !== undefined && typeof entry.strict !== 'boolean') {
|
|
71
|
+
throw new TypeError(`Kimten tool "${name}" strict must be a boolean when provided.`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
inputSchema: entry.inputSchema ?? z.any(),
|
|
76
|
+
execute: entry.execute,
|
|
77
|
+
description: entry.description,
|
|
78
|
+
strict: entry.strict,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
48
82
|
function toJsonSafe(value) {
|
|
49
83
|
if (value === undefined) {
|
|
50
84
|
return null;
|
package/package.json
CHANGED