@tabbybyte/kimten 0.1.1 → 0.1.3
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 +61 -27
- package/lib/tools.js +41 -7
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -54,11 +54,17 @@ Perfect for:
|
|
|
54
54
|
Feed the cat some treats:
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
|
-
npm i kimten ai zod @ai-sdk/openai
|
|
57
|
+
npm i @tabbybyte/kimten ai zod @ai-sdk/openai
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
That’s it. No ceremony. No rituals. 🍗
|
|
61
61
|
|
|
62
|
+
### Requirements
|
|
63
|
+
|
|
64
|
+
- Node `>=22`
|
|
65
|
+
- AI SDK Core `>=6`
|
|
66
|
+
- Zod `>=3`
|
|
67
|
+
|
|
62
68
|
---
|
|
63
69
|
|
|
64
70
|
## 🚀 Usage
|
|
@@ -68,7 +74,7 @@ Summon your little helper (with or without `toys`) and let it `play`.
|
|
|
68
74
|
```js
|
|
69
75
|
import { openai } from '@ai-sdk/openai'; // or, any other provider
|
|
70
76
|
import { z } from 'zod';
|
|
71
|
-
import Kimten from 'kimten';
|
|
77
|
+
import Kimten from '@tabbybyte/kimten';
|
|
72
78
|
|
|
73
79
|
const cat = Kimten({
|
|
74
80
|
brain: openai('gpt-4o-mini'), // or, any other available model
|
|
@@ -145,11 +151,20 @@ Create a new cat.
|
|
|
145
151
|
|
|
146
152
|
### Optional (extra whiskers)
|
|
147
153
|
|
|
148
|
-
* `toys` → object map of
|
|
154
|
+
* `toys` → object map of tool definitions. Each entry can be:
|
|
155
|
+
* async function shorthand: `async (args) => result`
|
|
156
|
+
* object form: `{ inputSchema?, description?, strict?, execute }`
|
|
157
|
+
default: `{}`
|
|
149
158
|
* `personality` → system prompt / behavior description (default: `"You are a helpful assistant."`)
|
|
150
159
|
* `hops` → max agent loop steps (default: `10`)
|
|
151
160
|
prevents infinite zoomies 🌀
|
|
152
161
|
|
|
162
|
+
### Tool semantics (important)
|
|
163
|
+
|
|
164
|
+
- Tool inputs are validated only if you provide `inputSchema` (shorthand tools accept anything).
|
|
165
|
+
- Tool results should be JSON-serializable; `undefined` becomes `null`.
|
|
166
|
+
- If a tool throws, Kimten returns `{ error, toolName }` as the tool result (it does not re-throw).
|
|
167
|
+
|
|
153
168
|
### Returns
|
|
154
169
|
|
|
155
170
|
* `play(input, schema?)`
|
|
@@ -164,10 +179,18 @@ Create a new cat.
|
|
|
164
179
|
|
|
165
180
|
---
|
|
166
181
|
|
|
167
|
-
## 🧩 Design Philosophy
|
|
182
|
+
## 🧩 Design Philosophy & Vibes
|
|
168
183
|
|
|
169
184
|
Kimten intentionally avoids “big agent framework energy”.
|
|
170
185
|
|
|
186
|
+
It’s meant to be:
|
|
187
|
+
|
|
188
|
+
* small
|
|
189
|
+
* opinionated
|
|
190
|
+
* dependency-light
|
|
191
|
+
* short-term memory by design
|
|
192
|
+
* easy to embed anywhere
|
|
193
|
+
|
|
171
194
|
No:
|
|
172
195
|
|
|
173
196
|
* streaming APIs
|
|
@@ -177,6 +200,7 @@ No:
|
|
|
177
200
|
* persistence/storage
|
|
178
201
|
* hidden background processes
|
|
179
202
|
* TypeScript runtime/build nonsense
|
|
203
|
+
* full fledged orchestration system
|
|
180
204
|
|
|
181
205
|
If you need those… use something heavier.
|
|
182
206
|
|
|
@@ -194,7 +218,7 @@ Refer to https://ai-sdk.dev/docs/foundations/providers-and-models
|
|
|
194
218
|
|
|
195
219
|
### Add tools freely
|
|
196
220
|
|
|
197
|
-
Tools
|
|
221
|
+
Tools can stay simple:
|
|
198
222
|
|
|
199
223
|
```js
|
|
200
224
|
toys: {
|
|
@@ -207,6 +231,38 @@ toys: {
|
|
|
207
231
|
|
|
208
232
|
The model decides when to use them.
|
|
209
233
|
|
|
234
|
+
For stronger arg validation and better tool selection, use object form:
|
|
235
|
+
|
|
236
|
+
```js
|
|
237
|
+
import { z } from 'zod';
|
|
238
|
+
|
|
239
|
+
toys: {
|
|
240
|
+
add: {
|
|
241
|
+
description: 'Add two numbers.',
|
|
242
|
+
inputSchema: z.object({ a: z.number(), b: z.number() }),
|
|
243
|
+
async execute({ a, b }) {
|
|
244
|
+
return a + b;
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Small “real” example
|
|
251
|
+
|
|
252
|
+
```js
|
|
253
|
+
toys: {
|
|
254
|
+
fetchJson: {
|
|
255
|
+
description: 'Fetch JSON from a URL (GET).',
|
|
256
|
+
inputSchema: z.object({ url: z.string().url() }),
|
|
257
|
+
async execute({ url }) {
|
|
258
|
+
const res = await fetch(url);
|
|
259
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
260
|
+
return res.json();
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
210
266
|
### Structured output = sanity
|
|
211
267
|
|
|
212
268
|
Use Zod schemas whenever possible.
|
|
@@ -223,28 +279,6 @@ Cats don’t hold grudges (or context). 🐾
|
|
|
223
279
|
|
|
224
280
|
---
|
|
225
281
|
|
|
226
|
-
## 🐾 Vibes
|
|
227
|
-
|
|
228
|
-
Kimten is:
|
|
229
|
-
|
|
230
|
-
* small
|
|
231
|
-
* opinionated
|
|
232
|
-
* dependency-light
|
|
233
|
-
* short-memory by design
|
|
234
|
-
* easy to embed anywhere
|
|
235
|
-
|
|
236
|
-
It’s not trying to be LangChain or a full orchestration system.
|
|
237
|
-
|
|
238
|
-
It’s just a cat.
|
|
239
|
-
|
|
240
|
-
A helpful one.
|
|
241
|
-
|
|
242
|
-
In your terminal.
|
|
243
|
-
|
|
244
|
-
Typing. 🐈⬛
|
|
245
|
-
|
|
246
|
-
---
|
|
247
|
-
|
|
248
282
|
## License
|
|
249
283
|
|
|
250
284
|
MIT
|
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