@tabbybyte/kimten 0.2.0 → 0.3.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 +10 -8
- package/index.d.ts +6 -2
- package/lib/kimten.js +67 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -99,7 +99,7 @@ cat.forget();
|
|
|
99
99
|
|
|
100
100
|
---
|
|
101
101
|
|
|
102
|
-
##
|
|
102
|
+
## 💭 Mental Model
|
|
103
103
|
|
|
104
104
|
Kimten is basically:
|
|
105
105
|
|
|
@@ -125,15 +125,15 @@ Each instance keeps short-term chat memory, so follow-up prompts naturally refer
|
|
|
125
125
|
Create a new instance.
|
|
126
126
|
|
|
127
127
|
#### Required
|
|
128
|
-
* `brain` → AI SDK model instance
|
|
128
|
+
* 🧠 `brain` → AI SDK model instance
|
|
129
129
|
|
|
130
130
|
#### Optional
|
|
131
131
|
|
|
132
|
-
* `toys` → object map of toy (tool) definitions. Each entry is:
|
|
132
|
+
* 🎱 `toys` → object map of toy (tool) definitions. Each entry is:
|
|
133
133
|
* object form: `{ inputSchema?, description?, strict?, execute }`
|
|
134
134
|
default: `{}`
|
|
135
|
-
* `personality` → system instructions / prompt for overall behavior description (default: `'You are a helpful assistant.'`)
|
|
136
|
-
* `hops` → max agent loop steps (default: `10`) - prevents infinite zoomies
|
|
135
|
+
* 🕵️♂️ `personality` → system instructions / prompt for overall behavior description (default: `'You are a helpful assistant.'`)
|
|
136
|
+
* 🌀 `hops` → max agent loop steps (default: `10`) - prevents infinite zoomies
|
|
137
137
|
|
|
138
138
|
#### Toy semantics
|
|
139
139
|
|
|
@@ -144,15 +144,17 @@ Create a new instance.
|
|
|
144
144
|
|
|
145
145
|
#### Returns
|
|
146
146
|
|
|
147
|
-
* `play(input, schema?)`
|
|
147
|
+
* `play(input, schema?, context?)`
|
|
148
148
|
|
|
149
149
|
* runs the agent
|
|
150
150
|
* uses short-term memory automatically
|
|
151
151
|
* optional Zod schema for structured output
|
|
152
|
+
* optional plain object context injected into the current call prompt as JSON (with basic redaction/truncation guards)
|
|
153
|
+
* context is ephemeral per `play()` call and is not persisted in memory
|
|
152
154
|
|
|
153
155
|
* `forget()`
|
|
154
156
|
|
|
155
|
-
* clears short-term memory
|
|
157
|
+
* clears short-term memory
|
|
156
158
|
|
|
157
159
|
---
|
|
158
160
|
|
|
@@ -164,7 +166,7 @@ For the `brain` part, feel free to use any compatible provider and their models.
|
|
|
164
166
|
|
|
165
167
|
❗ Note that not all providers (and models) may work out the box with Kimten, particularly for structured output.
|
|
166
168
|
|
|
167
|
-
💡 Refer to the AI SDK docs: **[providers and models](https://ai-sdk.dev/docs/foundations/providers-and-models)**.
|
|
169
|
+
💡 Refer to the AI SDK docs for details: **[providers and models](https://ai-sdk.dev/docs/foundations/providers-and-models)**.
|
|
168
170
|
|
|
169
171
|
### Add toys freely
|
|
170
172
|
|
package/index.d.ts
CHANGED
|
@@ -21,8 +21,12 @@ export type KimtenConfig = {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
export type KimtenAgent = {
|
|
24
|
-
play(input: string): Promise<string>;
|
|
25
|
-
play<S extends ZodTypeAny>(
|
|
24
|
+
play(input: string, schema?: null, context?: Record<string, unknown> | null): Promise<string>;
|
|
25
|
+
play<S extends ZodTypeAny>(
|
|
26
|
+
input: string,
|
|
27
|
+
schema: S,
|
|
28
|
+
context?: Record<string, unknown> | null
|
|
29
|
+
): Promise<ZodInfer<S>>;
|
|
26
30
|
forget(): void;
|
|
27
31
|
};
|
|
28
32
|
|
package/lib/kimten.js
CHANGED
|
@@ -3,6 +3,7 @@ import { createMemory } from './memory.js';
|
|
|
3
3
|
import { normalizeToys } from './tools.js';
|
|
4
4
|
|
|
5
5
|
const DEFAULT_PERSONALITY = 'You are a helpful assistant.';
|
|
6
|
+
const CONTEXT_CHAR_LIMIT = 4000;
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* @typedef {import('zod').ZodTypeAny} ZodSchema
|
|
@@ -59,7 +60,7 @@ const DEFAULT_PERSONALITY = 'You are a helpful assistant.';
|
|
|
59
60
|
* Returned Kimten instance.
|
|
60
61
|
*
|
|
61
62
|
* @typedef {object} KimtenAgent
|
|
62
|
-
* @property {(input: string, schema?: ZodSchema | null) => Promise<any>} play Run the agent loop.
|
|
63
|
+
* @property {(input: string, schema?: ZodSchema | null, context?: Record<string, unknown> | null) => Promise<any>} play Run the agent loop.
|
|
63
64
|
* @property {() => void} forget Clear short-term memory.
|
|
64
65
|
*/
|
|
65
66
|
|
|
@@ -91,6 +92,45 @@ function validateConfig(config) {
|
|
|
91
92
|
};
|
|
92
93
|
}
|
|
93
94
|
|
|
95
|
+
function serializeContext(context) {
|
|
96
|
+
if (context === null || context === undefined) {
|
|
97
|
+
return '';
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (typeof context !== 'object' || Array.isArray(context)) {
|
|
101
|
+
throw new TypeError('Kimten play(input, schema, context) expects context to be a plain object when provided.');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const redacted = JSON.stringify(
|
|
105
|
+
context,
|
|
106
|
+
(key, value) => {
|
|
107
|
+
const lowered = String(key).toLowerCase();
|
|
108
|
+
if (
|
|
109
|
+
lowered.includes('password') ||
|
|
110
|
+
lowered.includes('token') ||
|
|
111
|
+
lowered.includes('secret') ||
|
|
112
|
+
lowered.includes('apikey') ||
|
|
113
|
+
lowered.includes('api_key')
|
|
114
|
+
) {
|
|
115
|
+
return '[REDACTED]';
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return value;
|
|
119
|
+
},
|
|
120
|
+
2
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
if (typeof redacted !== 'string') {
|
|
124
|
+
return '';
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (redacted.length <= CONTEXT_CHAR_LIMIT) {
|
|
128
|
+
return redacted;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return `${redacted.slice(0, CONTEXT_CHAR_LIMIT)}\n...(truncated)`;
|
|
132
|
+
}
|
|
133
|
+
|
|
94
134
|
/**
|
|
95
135
|
* Create a tiny tool-using agent with short-term memory.
|
|
96
136
|
*
|
|
@@ -143,19 +183,41 @@ export function Kimten(config) {
|
|
|
143
183
|
*
|
|
144
184
|
* @param {string} input
|
|
145
185
|
* @param {ZodSchema | null} [schema]
|
|
186
|
+
* @param {Record<string, unknown> | null} [context]
|
|
146
187
|
* @returns {Promise<any>}
|
|
147
188
|
*/
|
|
148
|
-
async function play(input, schema = null) {
|
|
189
|
+
async function play(input, schema = null, context = null) {
|
|
149
190
|
if (typeof input !== 'string') {
|
|
150
191
|
throw new TypeError('Kimten play(input) expects input to be a string.');
|
|
151
192
|
}
|
|
152
193
|
|
|
194
|
+
// Serialize provided context (redacts sensitive keys and truncates if too long).
|
|
195
|
+
const serializedContext = serializeContext(context);
|
|
196
|
+
|
|
197
|
+
// If we have context, embed it before the user's message so the agent sees both.
|
|
198
|
+
const effectiveInput = serializedContext
|
|
199
|
+
? `Context (JSON):\n${serializedContext}\n\nUser message:\n${input}`
|
|
200
|
+
: input;
|
|
201
|
+
|
|
202
|
+
// Store the raw user message (no context) in short-term memory.
|
|
153
203
|
memory.add({ role: 'user', content: input });
|
|
154
204
|
|
|
205
|
+
// Retrieve conversation so far from memory.
|
|
206
|
+
const fetchedMessages = memory.list();
|
|
207
|
+
|
|
208
|
+
// If the last message is the user message we just added, we may need to replace it with
|
|
209
|
+
// a version that includes the serialized context, so the agent can see that information.
|
|
210
|
+
// This way we keep the raw user message in memory, but provide the agent with the enriched version.
|
|
211
|
+
const lastMessage = fetchedMessages[fetchedMessages.length - 1];
|
|
212
|
+
const messages = serializedContext && lastMessage?.role === 'user'
|
|
213
|
+
? [...fetchedMessages.slice(0, -1), { ...lastMessage, content: effectiveInput }]
|
|
214
|
+
: fetchedMessages;
|
|
215
|
+
|
|
216
|
+
// Choose a structured agent when a schema is provided, otherwise use the text agent.
|
|
155
217
|
const agent = schema ? getStructuredAgent(schema) : textAgent;
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
});
|
|
218
|
+
|
|
219
|
+
// Run the agent loop with the prepared messages.
|
|
220
|
+
const result = await agent.generate({ messages });
|
|
159
221
|
|
|
160
222
|
const assistantContent =
|
|
161
223
|
schema
|