@dot-ai/core 0.5.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/.ai/memory/2026-03-04.md +2 -0
- package/.ai/tasks.json +7 -0
- package/LICENSE +21 -0
- package/dist/__tests__/config.test.d.ts +2 -0
- package/dist/__tests__/config.test.d.ts.map +1 -0
- package/dist/__tests__/config.test.js +128 -0
- package/dist/__tests__/config.test.js.map +1 -0
- package/dist/__tests__/e2e.test.d.ts +2 -0
- package/dist/__tests__/e2e.test.d.ts.map +1 -0
- package/dist/__tests__/e2e.test.js +211 -0
- package/dist/__tests__/e2e.test.js.map +1 -0
- package/dist/__tests__/engine.test.d.ts +2 -0
- package/dist/__tests__/engine.test.d.ts.map +1 -0
- package/dist/__tests__/engine.test.js +271 -0
- package/dist/__tests__/engine.test.js.map +1 -0
- package/dist/__tests__/format.test.d.ts +2 -0
- package/dist/__tests__/format.test.d.ts.map +1 -0
- package/dist/__tests__/format.test.js +200 -0
- package/dist/__tests__/format.test.js.map +1 -0
- package/dist/__tests__/labels.test.d.ts +2 -0
- package/dist/__tests__/labels.test.d.ts.map +1 -0
- package/dist/__tests__/labels.test.js +82 -0
- package/dist/__tests__/labels.test.js.map +1 -0
- package/dist/__tests__/loader.test.d.ts +2 -0
- package/dist/__tests__/loader.test.d.ts.map +1 -0
- package/dist/__tests__/loader.test.js +161 -0
- package/dist/__tests__/loader.test.js.map +1 -0
- package/dist/__tests__/logger.test.d.ts +2 -0
- package/dist/__tests__/logger.test.d.ts.map +1 -0
- package/dist/__tests__/logger.test.js +95 -0
- package/dist/__tests__/logger.test.js.map +1 -0
- package/dist/__tests__/nodes.test.d.ts +2 -0
- package/dist/__tests__/nodes.test.d.ts.map +1 -0
- package/dist/__tests__/nodes.test.js +83 -0
- package/dist/__tests__/nodes.test.js.map +1 -0
- package/dist/config.d.ts +29 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +141 -0
- package/dist/config.js.map +1 -0
- package/dist/contracts.d.ts +56 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +2 -0
- package/dist/contracts.js.map +1 -0
- package/dist/engine.d.ts +38 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +88 -0
- package/dist/engine.js.map +1 -0
- package/dist/format.d.ts +18 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +89 -0
- package/dist/format.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/labels.d.ts +13 -0
- package/dist/labels.d.ts.map +1 -0
- package/dist/labels.js +36 -0
- package/dist/labels.js.map +1 -0
- package/dist/loader.d.ts +26 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +120 -0
- package/dist/loader.js.map +1 -0
- package/dist/logger.d.ts +29 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +29 -0
- package/dist/logger.js.map +1 -0
- package/dist/nodes.d.ts +15 -0
- package/dist/nodes.d.ts.map +1 -0
- package/dist/nodes.js +46 -0
- package/dist/nodes.js.map +1 -0
- package/dist/types.d.ts +111 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +23 -0
- package/src/__tests__/config.test.ts +166 -0
- package/src/__tests__/e2e.test.ts +257 -0
- package/src/__tests__/engine.test.ts +305 -0
- package/src/__tests__/format.test.ts +247 -0
- package/src/__tests__/labels.test.ts +96 -0
- package/src/__tests__/loader.test.ts +191 -0
- package/src/__tests__/logger.test.ts +113 -0
- package/src/__tests__/nodes.test.ts +103 -0
- package/src/config.ts +178 -0
- package/src/contracts.ts +71 -0
- package/src/engine.ts +145 -0
- package/src/format.ts +113 -0
- package/src/index.ts +63 -0
- package/src/labels.ts +40 -0
- package/src/loader.ts +152 -0
- package/src/logger.ts +49 -0
- package/src/nodes.ts +46 -0
- package/src/types.ts +123 -0
- package/tsconfig.json +23 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { boot, enrich, learn } from '../engine.js';
|
|
3
|
+
function createMockProviders(overrides) {
|
|
4
|
+
return {
|
|
5
|
+
memory: {
|
|
6
|
+
search: vi.fn().mockResolvedValue([]),
|
|
7
|
+
store: vi.fn().mockResolvedValue(undefined),
|
|
8
|
+
},
|
|
9
|
+
skills: {
|
|
10
|
+
list: vi.fn().mockResolvedValue([]),
|
|
11
|
+
match: vi.fn().mockResolvedValue([]),
|
|
12
|
+
load: vi.fn().mockResolvedValue(null),
|
|
13
|
+
},
|
|
14
|
+
identity: {
|
|
15
|
+
load: vi.fn().mockResolvedValue([]),
|
|
16
|
+
},
|
|
17
|
+
routing: {
|
|
18
|
+
route: vi.fn().mockResolvedValue({ model: 'sonnet', reason: 'default' }),
|
|
19
|
+
},
|
|
20
|
+
tasks: {
|
|
21
|
+
list: vi.fn().mockResolvedValue([]),
|
|
22
|
+
get: vi.fn().mockResolvedValue(null),
|
|
23
|
+
create: vi.fn(),
|
|
24
|
+
update: vi.fn(),
|
|
25
|
+
},
|
|
26
|
+
tools: {
|
|
27
|
+
list: vi.fn().mockResolvedValue([]),
|
|
28
|
+
match: vi.fn().mockResolvedValue([]),
|
|
29
|
+
load: vi.fn().mockResolvedValue(null),
|
|
30
|
+
},
|
|
31
|
+
...overrides,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
describe('boot', () => {
|
|
35
|
+
it('calls identity.load(), skills.list(), tools.list()', async () => {
|
|
36
|
+
const providers = createMockProviders();
|
|
37
|
+
await boot(providers);
|
|
38
|
+
expect(providers.identity.load).toHaveBeenCalledOnce();
|
|
39
|
+
expect(providers.skills.list).toHaveBeenCalledOnce();
|
|
40
|
+
expect(providers.tools.list).toHaveBeenCalledOnce();
|
|
41
|
+
});
|
|
42
|
+
it('returns a BootCache with identities, vocabulary, skills', async () => {
|
|
43
|
+
const providers = createMockProviders();
|
|
44
|
+
const cache = await boot(providers);
|
|
45
|
+
expect(cache).toHaveProperty('identities');
|
|
46
|
+
expect(cache).toHaveProperty('vocabulary');
|
|
47
|
+
expect(cache).toHaveProperty('skills');
|
|
48
|
+
});
|
|
49
|
+
it('populates identities from identity provider', async () => {
|
|
50
|
+
const mockIdentities = [
|
|
51
|
+
{ type: 'agents', content: 'I am Kiwi', source: 'file', priority: 1 },
|
|
52
|
+
];
|
|
53
|
+
const providers = createMockProviders({
|
|
54
|
+
identity: { load: vi.fn().mockResolvedValue(mockIdentities) },
|
|
55
|
+
});
|
|
56
|
+
const cache = await boot(providers);
|
|
57
|
+
expect(cache.identities).toEqual(mockIdentities);
|
|
58
|
+
});
|
|
59
|
+
it('populates skills from skills provider', async () => {
|
|
60
|
+
const mockSkills = [
|
|
61
|
+
{ name: 'dot-ai-tasks', description: 'Task management', labels: ['tasks', 'cockpit'] },
|
|
62
|
+
];
|
|
63
|
+
const providers = createMockProviders({
|
|
64
|
+
skills: {
|
|
65
|
+
list: vi.fn().mockResolvedValue(mockSkills),
|
|
66
|
+
match: vi.fn().mockResolvedValue([]),
|
|
67
|
+
load: vi.fn().mockResolvedValue(null),
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
const cache = await boot(providers);
|
|
71
|
+
expect(cache.skills).toEqual(mockSkills);
|
|
72
|
+
});
|
|
73
|
+
it('builds vocabulary from skill and tool labels', async () => {
|
|
74
|
+
const providers = createMockProviders({
|
|
75
|
+
skills: {
|
|
76
|
+
list: vi.fn().mockResolvedValue([
|
|
77
|
+
{ name: 'skill-a', description: 'A', labels: ['memory', 'routing'] },
|
|
78
|
+
]),
|
|
79
|
+
match: vi.fn().mockResolvedValue([]),
|
|
80
|
+
load: vi.fn().mockResolvedValue(null),
|
|
81
|
+
},
|
|
82
|
+
tools: {
|
|
83
|
+
list: vi.fn().mockResolvedValue([
|
|
84
|
+
{ name: 'tool-b', description: 'B', labels: ['ui', 'ux'], config: {}, source: 'file' },
|
|
85
|
+
]),
|
|
86
|
+
match: vi.fn().mockResolvedValue([]),
|
|
87
|
+
load: vi.fn().mockResolvedValue(null),
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
const cache = await boot(providers);
|
|
91
|
+
expect(cache.vocabulary).toContain('memory');
|
|
92
|
+
expect(cache.vocabulary).toContain('routing');
|
|
93
|
+
expect(cache.vocabulary).toContain('ui');
|
|
94
|
+
expect(cache.vocabulary).toContain('ux');
|
|
95
|
+
});
|
|
96
|
+
it('calls identity, skills, and tools providers in parallel (all called before any awaited)', async () => {
|
|
97
|
+
const callOrder = [];
|
|
98
|
+
const providers = createMockProviders({
|
|
99
|
+
identity: {
|
|
100
|
+
load: vi.fn().mockImplementation(async () => {
|
|
101
|
+
callOrder.push('identity');
|
|
102
|
+
return [];
|
|
103
|
+
}),
|
|
104
|
+
},
|
|
105
|
+
skills: {
|
|
106
|
+
list: vi.fn().mockImplementation(async () => {
|
|
107
|
+
callOrder.push('skills');
|
|
108
|
+
return [];
|
|
109
|
+
}),
|
|
110
|
+
match: vi.fn().mockResolvedValue([]),
|
|
111
|
+
load: vi.fn().mockResolvedValue(null),
|
|
112
|
+
},
|
|
113
|
+
tools: {
|
|
114
|
+
list: vi.fn().mockImplementation(async () => {
|
|
115
|
+
callOrder.push('tools');
|
|
116
|
+
return [];
|
|
117
|
+
}),
|
|
118
|
+
match: vi.fn().mockResolvedValue([]),
|
|
119
|
+
load: vi.fn().mockResolvedValue(null),
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
await boot(providers);
|
|
123
|
+
// All three should have been called (order may vary in parallel)
|
|
124
|
+
expect(callOrder).toContain('identity');
|
|
125
|
+
expect(callOrder).toContain('skills');
|
|
126
|
+
expect(callOrder).toContain('tools');
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
describe('enrich', () => {
|
|
130
|
+
const baseCache = {
|
|
131
|
+
identities: [{ type: 'agents', content: 'I am Kiwi', source: 'file', priority: 1 }],
|
|
132
|
+
vocabulary: ['memory', 'routing', 'tasks'],
|
|
133
|
+
skills: [],
|
|
134
|
+
};
|
|
135
|
+
it('returns an EnrichedContext with all required fields', async () => {
|
|
136
|
+
const providers = createMockProviders();
|
|
137
|
+
const result = await enrich('fix the memory issue', providers, baseCache);
|
|
138
|
+
expect(result).toHaveProperty('prompt');
|
|
139
|
+
expect(result).toHaveProperty('labels');
|
|
140
|
+
expect(result).toHaveProperty('identities');
|
|
141
|
+
expect(result).toHaveProperty('memories');
|
|
142
|
+
expect(result).toHaveProperty('skills');
|
|
143
|
+
expect(result).toHaveProperty('tools');
|
|
144
|
+
expect(result).toHaveProperty('routing');
|
|
145
|
+
});
|
|
146
|
+
it('includes the original prompt in the result', async () => {
|
|
147
|
+
const providers = createMockProviders();
|
|
148
|
+
const result = await enrich('fix the memory issue', providers, baseCache);
|
|
149
|
+
expect(result.prompt).toBe('fix the memory issue');
|
|
150
|
+
});
|
|
151
|
+
it('extracts labels from prompt against vocabulary', async () => {
|
|
152
|
+
const providers = createMockProviders();
|
|
153
|
+
const result = await enrich('fix the memory issue', providers, baseCache);
|
|
154
|
+
const labelNames = result.labels.map((l) => l.name);
|
|
155
|
+
expect(labelNames).toContain('memory');
|
|
156
|
+
expect(labelNames).not.toContain('routing');
|
|
157
|
+
});
|
|
158
|
+
it('includes identities from cache', async () => {
|
|
159
|
+
const providers = createMockProviders();
|
|
160
|
+
const result = await enrich('hello', providers, baseCache);
|
|
161
|
+
expect(result.identities).toEqual(baseCache.identities);
|
|
162
|
+
});
|
|
163
|
+
it('calls memory.search with prompt and extracted label names', async () => {
|
|
164
|
+
const providers = createMockProviders();
|
|
165
|
+
await enrich('fix the memory issue', providers, baseCache);
|
|
166
|
+
expect(providers.memory.search).toHaveBeenCalledWith('fix the memory issue', ['memory']);
|
|
167
|
+
});
|
|
168
|
+
it('calls skills.match with extracted labels', async () => {
|
|
169
|
+
const providers = createMockProviders();
|
|
170
|
+
await enrich('fix the routing logic', providers, baseCache);
|
|
171
|
+
expect(providers.skills.match).toHaveBeenCalledWith(expect.arrayContaining([expect.objectContaining({ name: 'routing' })]));
|
|
172
|
+
});
|
|
173
|
+
it('calls tools.match with extracted labels', async () => {
|
|
174
|
+
const providers = createMockProviders();
|
|
175
|
+
await enrich('tasks need fixing', providers, baseCache);
|
|
176
|
+
expect(providers.tools.match).toHaveBeenCalledWith(expect.arrayContaining([expect.objectContaining({ name: 'tasks' })]));
|
|
177
|
+
});
|
|
178
|
+
it('calls routing.route with extracted labels', async () => {
|
|
179
|
+
const providers = createMockProviders();
|
|
180
|
+
await enrich('fix the memory issue', providers, baseCache);
|
|
181
|
+
expect(providers.routing.route).toHaveBeenCalledWith(expect.arrayContaining([expect.objectContaining({ name: 'memory' })]));
|
|
182
|
+
});
|
|
183
|
+
it('populates memories from memory.search result', async () => {
|
|
184
|
+
const mockMemories = [
|
|
185
|
+
{ content: 'Memory fact', type: 'fact', source: 'file' },
|
|
186
|
+
];
|
|
187
|
+
const providers = createMockProviders({
|
|
188
|
+
memory: {
|
|
189
|
+
search: vi.fn().mockResolvedValue(mockMemories),
|
|
190
|
+
store: vi.fn().mockResolvedValue(undefined),
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
const result = await enrich('fix the memory issue', providers, baseCache);
|
|
194
|
+
expect(result.memories).toEqual(mockMemories);
|
|
195
|
+
});
|
|
196
|
+
it('populates skills from skills.match result', async () => {
|
|
197
|
+
const mockSkills = [
|
|
198
|
+
{ name: 'dot-ai-tasks', description: 'Tasks', labels: ['tasks'] },
|
|
199
|
+
];
|
|
200
|
+
const providers = createMockProviders({
|
|
201
|
+
skills: {
|
|
202
|
+
list: vi.fn().mockResolvedValue([]),
|
|
203
|
+
match: vi.fn().mockResolvedValue(mockSkills),
|
|
204
|
+
load: vi.fn().mockResolvedValue(null),
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
const result = await enrich('hello', providers, baseCache);
|
|
208
|
+
expect(result.skills).toEqual(mockSkills);
|
|
209
|
+
});
|
|
210
|
+
it('populates routing from routing.route result', async () => {
|
|
211
|
+
const mockRouting = { model: 'opus', reason: 'complex task' };
|
|
212
|
+
const providers = createMockProviders({
|
|
213
|
+
routing: { route: vi.fn().mockResolvedValue(mockRouting) },
|
|
214
|
+
});
|
|
215
|
+
const result = await enrich('hello', providers, baseCache);
|
|
216
|
+
expect(result.routing).toEqual(mockRouting);
|
|
217
|
+
});
|
|
218
|
+
it('calls memory, skills, tools, routing in parallel', async () => {
|
|
219
|
+
const callOrder = [];
|
|
220
|
+
const providers = createMockProviders({
|
|
221
|
+
memory: {
|
|
222
|
+
search: vi.fn().mockImplementation(async () => { callOrder.push('memory'); return []; }),
|
|
223
|
+
store: vi.fn().mockResolvedValue(undefined),
|
|
224
|
+
},
|
|
225
|
+
skills: {
|
|
226
|
+
list: vi.fn().mockResolvedValue([]),
|
|
227
|
+
match: vi.fn().mockImplementation(async () => { callOrder.push('skills'); return []; }),
|
|
228
|
+
load: vi.fn().mockResolvedValue(null),
|
|
229
|
+
},
|
|
230
|
+
tools: {
|
|
231
|
+
list: vi.fn().mockResolvedValue([]),
|
|
232
|
+
match: vi.fn().mockImplementation(async () => { callOrder.push('tools'); return []; }),
|
|
233
|
+
load: vi.fn().mockResolvedValue(null),
|
|
234
|
+
},
|
|
235
|
+
routing: {
|
|
236
|
+
route: vi.fn().mockImplementation(async () => { callOrder.push('routing'); return { model: 'sonnet', reason: 'default' }; }),
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
await enrich('hello world', providers, baseCache);
|
|
240
|
+
expect(callOrder).toContain('memory');
|
|
241
|
+
expect(callOrder).toContain('skills');
|
|
242
|
+
expect(callOrder).toContain('tools');
|
|
243
|
+
expect(callOrder).toContain('routing');
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
describe('learn', () => {
|
|
247
|
+
it('calls memory.store with the response', async () => {
|
|
248
|
+
const providers = createMockProviders();
|
|
249
|
+
await learn('This is what I learned today', providers);
|
|
250
|
+
expect(providers.memory.store).toHaveBeenCalledOnce();
|
|
251
|
+
expect(providers.memory.store).toHaveBeenCalledWith(expect.objectContaining({ content: 'This is what I learned today', type: 'log' }));
|
|
252
|
+
});
|
|
253
|
+
it('stores entry with today\'s date', async () => {
|
|
254
|
+
const providers = createMockProviders();
|
|
255
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
256
|
+
await learn('response', providers);
|
|
257
|
+
expect(providers.memory.store).toHaveBeenCalledWith(expect.objectContaining({ date: today }));
|
|
258
|
+
});
|
|
259
|
+
it('does not call any other provider methods', async () => {
|
|
260
|
+
const providers = createMockProviders();
|
|
261
|
+
await learn('response', providers);
|
|
262
|
+
expect(providers.skills.list).not.toHaveBeenCalled();
|
|
263
|
+
expect(providers.identity.load).not.toHaveBeenCalled();
|
|
264
|
+
expect(providers.routing.route).not.toHaveBeenCalled();
|
|
265
|
+
});
|
|
266
|
+
it('resolves without error on successful store', async () => {
|
|
267
|
+
const providers = createMockProviders();
|
|
268
|
+
await expect(learn('response', providers)).resolves.toBeUndefined();
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
//# sourceMappingURL=engine.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.test.js","sourceRoot":"","sources":["../../src/__tests__/engine.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/format.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { formatContext } from '../format.js';
|
|
3
|
+
function makeContext(overrides) {
|
|
4
|
+
return {
|
|
5
|
+
prompt: 'test prompt',
|
|
6
|
+
labels: [],
|
|
7
|
+
identities: [],
|
|
8
|
+
memories: [],
|
|
9
|
+
skills: [],
|
|
10
|
+
tools: [],
|
|
11
|
+
routing: { model: 'default', reason: '' },
|
|
12
|
+
...overrides,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function makeIdentity(overrides) {
|
|
16
|
+
return {
|
|
17
|
+
type: 'agents',
|
|
18
|
+
content: 'You are Kiwi.',
|
|
19
|
+
source: 'file',
|
|
20
|
+
priority: 10,
|
|
21
|
+
...overrides,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function makeMemory(overrides) {
|
|
25
|
+
return {
|
|
26
|
+
content: 'User prefers TypeScript',
|
|
27
|
+
type: 'fact',
|
|
28
|
+
source: 'file',
|
|
29
|
+
...overrides,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function makeSkill(overrides) {
|
|
33
|
+
return {
|
|
34
|
+
name: 'my-skill',
|
|
35
|
+
description: 'A skill',
|
|
36
|
+
labels: [],
|
|
37
|
+
content: 'Skill content here.',
|
|
38
|
+
...overrides,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function makeTool(overrides) {
|
|
42
|
+
return {
|
|
43
|
+
name: 'bash',
|
|
44
|
+
description: 'Run shell commands',
|
|
45
|
+
labels: [],
|
|
46
|
+
config: {},
|
|
47
|
+
source: 'file',
|
|
48
|
+
...overrides,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
describe('formatContext', () => {
|
|
52
|
+
it('includes all sections when identities, memories, skills, and tools are present', () => {
|
|
53
|
+
const ctx = makeContext({
|
|
54
|
+
identities: [makeIdentity({ content: 'You are Kiwi.' })],
|
|
55
|
+
memories: [makeMemory({ content: 'User prefers TypeScript' })],
|
|
56
|
+
skills: [makeSkill({ name: 'dot-ai', content: 'dot-ai skill content' })],
|
|
57
|
+
tools: [makeTool({ name: 'bash', description: 'Run shell commands' })],
|
|
58
|
+
});
|
|
59
|
+
const result = formatContext(ctx);
|
|
60
|
+
expect(result).toContain('You are Kiwi.');
|
|
61
|
+
expect(result).toContain('## Relevant Memory');
|
|
62
|
+
expect(result).toContain('User prefers TypeScript');
|
|
63
|
+
expect(result).toContain('## Active Skills');
|
|
64
|
+
expect(result).toContain('dot-ai skill content');
|
|
65
|
+
expect(result).toContain('## Available Tools');
|
|
66
|
+
expect(result).toContain('bash');
|
|
67
|
+
});
|
|
68
|
+
it('skips identities when skipIdentities: true', () => {
|
|
69
|
+
const ctx = makeContext({
|
|
70
|
+
identities: [makeIdentity({ content: 'You are Kiwi.' })],
|
|
71
|
+
memories: [makeMemory({ content: 'Some memory' })],
|
|
72
|
+
});
|
|
73
|
+
const result = formatContext(ctx, { skipIdentities: true });
|
|
74
|
+
expect(result).not.toContain('You are Kiwi.');
|
|
75
|
+
expect(result).toContain('## Relevant Memory');
|
|
76
|
+
});
|
|
77
|
+
it('includes identities when skipIdentities: false', () => {
|
|
78
|
+
const ctx = makeContext({
|
|
79
|
+
identities: [makeIdentity({ content: 'You are Kiwi.' })],
|
|
80
|
+
});
|
|
81
|
+
const result = formatContext(ctx, { skipIdentities: false });
|
|
82
|
+
expect(result).toContain('You are Kiwi.');
|
|
83
|
+
});
|
|
84
|
+
it('includes identities when skipIdentities is undefined (backward compat)', () => {
|
|
85
|
+
const ctx = makeContext({
|
|
86
|
+
identities: [makeIdentity({ content: 'You are Kiwi.' })],
|
|
87
|
+
});
|
|
88
|
+
const result = formatContext(ctx);
|
|
89
|
+
expect(result).toContain('You are Kiwi.');
|
|
90
|
+
});
|
|
91
|
+
it('sorts identities by priority descending', () => {
|
|
92
|
+
const ctx = makeContext({
|
|
93
|
+
identities: [
|
|
94
|
+
makeIdentity({ content: 'Low priority identity.', priority: 1 }),
|
|
95
|
+
makeIdentity({ content: 'High priority identity.', priority: 100 }),
|
|
96
|
+
],
|
|
97
|
+
});
|
|
98
|
+
const result = formatContext(ctx);
|
|
99
|
+
const highPos = result.indexOf('High priority identity.');
|
|
100
|
+
const lowPos = result.indexOf('Low priority identity.');
|
|
101
|
+
expect(highPos).toBeLessThan(lowPos);
|
|
102
|
+
});
|
|
103
|
+
it('truncates skill content at maxSkillLength with [...truncated] marker', () => {
|
|
104
|
+
const longContent = 'A'.repeat(200);
|
|
105
|
+
const ctx = makeContext({
|
|
106
|
+
skills: [makeSkill({ content: longContent })],
|
|
107
|
+
});
|
|
108
|
+
const result = formatContext(ctx, { maxSkillLength: 50 });
|
|
109
|
+
expect(result).toContain('A'.repeat(50));
|
|
110
|
+
expect(result).toContain('[...truncated]');
|
|
111
|
+
expect(result).not.toContain('A'.repeat(51));
|
|
112
|
+
});
|
|
113
|
+
it('does not truncate skill content shorter than maxSkillLength', () => {
|
|
114
|
+
const ctx = makeContext({
|
|
115
|
+
skills: [makeSkill({ content: 'Short content.' })],
|
|
116
|
+
});
|
|
117
|
+
const result = formatContext(ctx, { maxSkillLength: 200 });
|
|
118
|
+
expect(result).toContain('Short content.');
|
|
119
|
+
expect(result).not.toContain('[...truncated]');
|
|
120
|
+
});
|
|
121
|
+
it('limits number of skills to maxSkills', () => {
|
|
122
|
+
const ctx = makeContext({
|
|
123
|
+
skills: [
|
|
124
|
+
makeSkill({ name: 'skill-a', content: 'Content A' }),
|
|
125
|
+
makeSkill({ name: 'skill-b', content: 'Content B' }),
|
|
126
|
+
makeSkill({ name: 'skill-c', content: 'Content C' }),
|
|
127
|
+
],
|
|
128
|
+
});
|
|
129
|
+
const result = formatContext(ctx, { maxSkills: 2 });
|
|
130
|
+
expect(result).toContain('skill-a');
|
|
131
|
+
expect(result).toContain('Content A');
|
|
132
|
+
expect(result).toContain('skill-b');
|
|
133
|
+
expect(result).toContain('Content B');
|
|
134
|
+
expect(result).not.toContain('skill-c');
|
|
135
|
+
expect(result).not.toContain('Content C');
|
|
136
|
+
});
|
|
137
|
+
it('combines skipIdentities + maxSkillLength + maxSkills', () => {
|
|
138
|
+
const ctx = makeContext({
|
|
139
|
+
identities: [makeIdentity({ content: 'You are Kiwi.' })],
|
|
140
|
+
skills: [
|
|
141
|
+
makeSkill({ name: 'skill-a', content: 'A'.repeat(100) }),
|
|
142
|
+
makeSkill({ name: 'skill-b', content: 'B'.repeat(100) }),
|
|
143
|
+
makeSkill({ name: 'skill-c', content: 'C'.repeat(100) }),
|
|
144
|
+
],
|
|
145
|
+
});
|
|
146
|
+
const result = formatContext(ctx, {
|
|
147
|
+
skipIdentities: true,
|
|
148
|
+
maxSkillLength: 20,
|
|
149
|
+
maxSkills: 2,
|
|
150
|
+
});
|
|
151
|
+
expect(result).not.toContain('You are Kiwi.');
|
|
152
|
+
expect(result).toContain('skill-a');
|
|
153
|
+
expect(result).toContain('skill-b');
|
|
154
|
+
expect(result).not.toContain('skill-c');
|
|
155
|
+
expect(result).toContain('[...truncated]');
|
|
156
|
+
expect(result).not.toContain('A'.repeat(21));
|
|
157
|
+
});
|
|
158
|
+
it('returns empty string when context has all empty arrays', () => {
|
|
159
|
+
const ctx = makeContext();
|
|
160
|
+
const result = formatContext(ctx);
|
|
161
|
+
expect(result).toBe('');
|
|
162
|
+
});
|
|
163
|
+
it('omits routing section when model is "default"', () => {
|
|
164
|
+
const ctx = makeContext({
|
|
165
|
+
routing: { model: 'default', reason: 'no routing needed' },
|
|
166
|
+
});
|
|
167
|
+
const result = formatContext(ctx);
|
|
168
|
+
expect(result).not.toContain('## Model Routing');
|
|
169
|
+
});
|
|
170
|
+
it('includes routing section when model is not "default"', () => {
|
|
171
|
+
const ctx = makeContext({
|
|
172
|
+
routing: { model: 'opus', reason: 'complex task' },
|
|
173
|
+
});
|
|
174
|
+
const result = formatContext(ctx);
|
|
175
|
+
expect(result).toContain('## Model Routing');
|
|
176
|
+
expect(result).toContain('opus');
|
|
177
|
+
expect(result).toContain('complex task');
|
|
178
|
+
});
|
|
179
|
+
it('separates multiple sections with ---', () => {
|
|
180
|
+
const ctx = makeContext({
|
|
181
|
+
identities: [makeIdentity({ content: 'Identity content.' })],
|
|
182
|
+
memories: [makeMemory({ content: 'A memory.' })],
|
|
183
|
+
});
|
|
184
|
+
const result = formatContext(ctx);
|
|
185
|
+
expect(result).toContain('---');
|
|
186
|
+
});
|
|
187
|
+
it('skips skills without content', () => {
|
|
188
|
+
const ctx = makeContext({
|
|
189
|
+
skills: [
|
|
190
|
+
makeSkill({ name: 'no-content', content: undefined }),
|
|
191
|
+
makeSkill({ name: 'has-content', content: 'Real content' }),
|
|
192
|
+
],
|
|
193
|
+
});
|
|
194
|
+
const result = formatContext(ctx);
|
|
195
|
+
expect(result).toContain('has-content');
|
|
196
|
+
expect(result).toContain('Real content');
|
|
197
|
+
expect(result).not.toContain('no-content');
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
//# sourceMappingURL=format.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.test.js","sourceRoot":"","sources":["../../src/__tests__/format.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labels.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/labels.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { extractLabels, buildVocabulary } from '../labels.js';
|
|
3
|
+
describe('extractLabels', () => {
|
|
4
|
+
it('returns matched labels from vocabulary', () => {
|
|
5
|
+
const labels = extractLabels('I need to fix the memory issue', ['memory', 'routing', 'skills']);
|
|
6
|
+
expect(labels).toHaveLength(1);
|
|
7
|
+
expect(labels[0]).toEqual({ name: 'memory', source: 'extract' });
|
|
8
|
+
});
|
|
9
|
+
it('returns multiple matches when several vocabulary words are present', () => {
|
|
10
|
+
const labels = extractLabels('routing and memory both matter', ['memory', 'routing', 'skills']);
|
|
11
|
+
expect(labels).toHaveLength(2);
|
|
12
|
+
const names = labels.map((l) => l.name);
|
|
13
|
+
expect(names).toContain('memory');
|
|
14
|
+
expect(names).toContain('routing');
|
|
15
|
+
});
|
|
16
|
+
it('returns empty array when no vocabulary words match', () => {
|
|
17
|
+
const labels = extractLabels('hello world', ['memory', 'routing', 'skills']);
|
|
18
|
+
expect(labels).toHaveLength(0);
|
|
19
|
+
});
|
|
20
|
+
it('is case insensitive', () => {
|
|
21
|
+
const labels = extractLabels('MEMORY is important', ['memory']);
|
|
22
|
+
expect(labels).toHaveLength(1);
|
|
23
|
+
expect(labels[0].name).toBe('memory');
|
|
24
|
+
});
|
|
25
|
+
it('is case insensitive for vocabulary words too', () => {
|
|
26
|
+
const labels = extractLabels('memory is important', ['Memory']);
|
|
27
|
+
expect(labels).toHaveLength(1);
|
|
28
|
+
expect(labels[0].name).toBe('Memory');
|
|
29
|
+
});
|
|
30
|
+
it('sets source to "extract" for all labels', () => {
|
|
31
|
+
const labels = extractLabels('use routing for memory', ['routing', 'memory']);
|
|
32
|
+
for (const label of labels) {
|
|
33
|
+
expect(label.source).toBe('extract');
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
it('returns empty array when vocabulary is empty', () => {
|
|
37
|
+
const labels = extractLabels('any prompt at all', []);
|
|
38
|
+
expect(labels).toHaveLength(0);
|
|
39
|
+
});
|
|
40
|
+
it('does not match partial words within a prompt', () => {
|
|
41
|
+
const labels = extractLabels('my skillset is broad', ['skill']);
|
|
42
|
+
expect(labels).toHaveLength(0);
|
|
43
|
+
});
|
|
44
|
+
it('matches whole words at word boundaries', () => {
|
|
45
|
+
const labels = extractLabels('my skill is broad', ['skill']);
|
|
46
|
+
expect(labels).toHaveLength(1);
|
|
47
|
+
expect(labels[0].name).toBe('skill');
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
describe('buildVocabulary', () => {
|
|
51
|
+
it('merges skill labels and tool labels into a flat array', () => {
|
|
52
|
+
const vocab = buildVocabulary([['memory', 'routing']], [['ui', 'ux']]);
|
|
53
|
+
expect(vocab).toContain('memory');
|
|
54
|
+
expect(vocab).toContain('routing');
|
|
55
|
+
expect(vocab).toContain('ui');
|
|
56
|
+
expect(vocab).toContain('ux');
|
|
57
|
+
});
|
|
58
|
+
it('deduplicates labels appearing in multiple skills', () => {
|
|
59
|
+
const vocab = buildVocabulary([['memory', 'routing'], ['memory', 'skills']], []);
|
|
60
|
+
const memoryCount = vocab.filter((v) => v === 'memory').length;
|
|
61
|
+
expect(memoryCount).toBe(1);
|
|
62
|
+
});
|
|
63
|
+
it('deduplicates labels appearing across skills and tools', () => {
|
|
64
|
+
const vocab = buildVocabulary([['shared']], [['shared']]);
|
|
65
|
+
const count = vocab.filter((v) => v === 'shared').length;
|
|
66
|
+
expect(count).toBe(1);
|
|
67
|
+
});
|
|
68
|
+
it('returns empty array when both inputs are empty', () => {
|
|
69
|
+
const vocab = buildVocabulary([], []);
|
|
70
|
+
expect(vocab).toHaveLength(0);
|
|
71
|
+
});
|
|
72
|
+
it('handles empty skill label arrays', () => {
|
|
73
|
+
const vocab = buildVocabulary([[], []], [['tool-label']]);
|
|
74
|
+
expect(vocab).toEqual(['tool-label']);
|
|
75
|
+
});
|
|
76
|
+
it('returns unique values only', () => {
|
|
77
|
+
const vocab = buildVocabulary([['a', 'b', 'a']], [['b', 'c']]);
|
|
78
|
+
expect(vocab.length).toBe(3);
|
|
79
|
+
expect(new Set(vocab).size).toBe(3);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
//# sourceMappingURL=labels.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labels.test.js","sourceRoot":"","sources":["../../src/__tests__/labels.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/loader.test.ts"],"names":[],"mappings":""}
|