@gethmy/mcp 2.4.7 → 2.5.1
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 +36 -20
- package/dist/cli.js +1857 -30209
- package/dist/index.js +1323 -26686
- package/dist/lib/api-client.js +122 -925
- package/package.json +4 -3
- package/src/api-client.ts +129 -96
- package/src/memory-floor.ts +264 -0
- package/src/memory-park.ts +252 -0
- package/src/memory-session.ts +61 -0
- package/src/prompt-builder.ts +93 -0
- package/src/server.ts +351 -1467
- package/dist/http.js +0 -1959
- package/dist/remote.js +0 -32328
- package/dist/server.js +0 -31967
- package/src/__tests__/active-learning.test.ts +0 -483
- package/src/__tests__/agent-performance-profiles.test.ts +0 -468
- package/src/__tests__/auto-session.test.ts +0 -912
- package/src/__tests__/context-assembly.test.ts +0 -506
- package/src/__tests__/graph-expansion.test.ts +0 -285
- package/src/__tests__/integration-memory-crud.test.ts +0 -948
- package/src/__tests__/integration-memory-system.test.ts +0 -321
- package/src/__tests__/lifecycle-maintenance.test.ts +0 -238
- package/src/__tests__/memory-audit.test.ts +0 -528
- package/src/__tests__/pattern-detection.test.ts +0 -438
- package/src/__tests__/prompt-builder.test.ts +0 -505
- package/src/__tests__/remote-routing.test.ts +0 -285
- package/src/active-learning.ts +0 -1165
- package/src/consolidation.ts +0 -383
- package/src/context-assembly.ts +0 -1175
- package/src/lifecycle-maintenance.ts +0 -120
- package/src/memory-audit.ts +0 -578
- package/src/memory-cleanup.ts +0 -902
|
@@ -1,468 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unit + integration tests for Agent Performance Profiles.
|
|
3
|
-
*
|
|
4
|
-
* Unit tests verify that runEndSessionPipeline correctly refreshes
|
|
5
|
-
* the materialized view and upserts an "agent" knowledge entity.
|
|
6
|
-
*
|
|
7
|
-
* Integration tests (skipped when not configured) call the real API.
|
|
8
|
-
*
|
|
9
|
-
* Run with: bun test packages/mcp-server/src/__tests__/agent-performance-profiles.test.ts
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { describe, expect, mock, test } from "bun:test";
|
|
13
|
-
|
|
14
|
-
// ============================================================
|
|
15
|
-
// Module mocks (must be before imports)
|
|
16
|
-
// ============================================================
|
|
17
|
-
|
|
18
|
-
const mockWorkspaceId: string | null = "ws-test-123";
|
|
19
|
-
const mockProjectId: string | null = "proj-test-456";
|
|
20
|
-
|
|
21
|
-
mock.module("../config.js", () => ({
|
|
22
|
-
getActiveWorkspaceId: () => mockWorkspaceId,
|
|
23
|
-
getActiveProjectId: () => mockProjectId,
|
|
24
|
-
isConfigured: () => true,
|
|
25
|
-
loadConfig: () => {},
|
|
26
|
-
getApiUrl: () => "http://localhost:54321",
|
|
27
|
-
getApiKey: () => "test-key",
|
|
28
|
-
getMemoryDir: () => null,
|
|
29
|
-
getUserEmail: () => null,
|
|
30
|
-
saveConfig: () => {},
|
|
31
|
-
setActiveProject: () => {},
|
|
32
|
-
setActiveWorkspace: () => {},
|
|
33
|
-
resetClient: () => {},
|
|
34
|
-
}));
|
|
35
|
-
|
|
36
|
-
mock.module("../active-learning.js", () => ({
|
|
37
|
-
extractLearnings: mock(async () => ({ count: 0, entityIds: [] })),
|
|
38
|
-
extractMidSessionLearnings: mock(async () => ({ count: 0, entityIds: [] })),
|
|
39
|
-
detectContradictions: mock(async () => ({ contradictions: [] })),
|
|
40
|
-
}));
|
|
41
|
-
|
|
42
|
-
mock.module("../context-assembly.js", () => ({
|
|
43
|
-
recordContextFeedback: mock(async () => ({ adjusted: 0 })),
|
|
44
|
-
assembleContext: mock(async () => ({ entities: [], markdown: "" })),
|
|
45
|
-
cacheManifest: mock(() => {}),
|
|
46
|
-
computeRelevanceScore: mock(() => 0),
|
|
47
|
-
getCachedManifest: mock(() => null),
|
|
48
|
-
mapToContextEntity: mock(() => ({})),
|
|
49
|
-
trackSessionAssembly: mock(async () => ({})),
|
|
50
|
-
}));
|
|
51
|
-
|
|
52
|
-
mock.module("../lifecycle-maintenance.js", () => ({
|
|
53
|
-
runLifecycleMaintenance: mock(async () => ({
|
|
54
|
-
archived: 0,
|
|
55
|
-
pruned: 0,
|
|
56
|
-
promoted: 0,
|
|
57
|
-
reviewed: 0,
|
|
58
|
-
})),
|
|
59
|
-
}));
|
|
60
|
-
|
|
61
|
-
mock.module("../consolidation.js", () => ({
|
|
62
|
-
consolidateMemories: mock(async () => ({ consolidated: 0 })),
|
|
63
|
-
}));
|
|
64
|
-
|
|
65
|
-
mock.module("../graph-expansion.js", () => ({
|
|
66
|
-
autoExpandGraph: mock(async () => {}),
|
|
67
|
-
}));
|
|
68
|
-
|
|
69
|
-
// Import after mocking
|
|
70
|
-
const { runEndSessionPipeline } = await import("../server.js");
|
|
71
|
-
|
|
72
|
-
// ============================================================
|
|
73
|
-
// Helpers
|
|
74
|
-
// ============================================================
|
|
75
|
-
|
|
76
|
-
const flush = () => new Promise((r) => setTimeout(r, 100));
|
|
77
|
-
|
|
78
|
-
function makeMockClient() {
|
|
79
|
-
const createdEntities: Array<Record<string, unknown>> = [];
|
|
80
|
-
let nextId = 1;
|
|
81
|
-
|
|
82
|
-
return {
|
|
83
|
-
createdEntities,
|
|
84
|
-
getCard: mock(async () => ({
|
|
85
|
-
card: {
|
|
86
|
-
title: "Test card",
|
|
87
|
-
description: "desc",
|
|
88
|
-
labels: [],
|
|
89
|
-
subtasks: [],
|
|
90
|
-
},
|
|
91
|
-
})),
|
|
92
|
-
removeLabelFromCard: mock(async () => ({ success: true })),
|
|
93
|
-
createMemoryEntity: mock(async (data: Record<string, unknown>) => {
|
|
94
|
-
const entity = { id: `entity-${nextId++}`, ...data };
|
|
95
|
-
createdEntities.push(entity);
|
|
96
|
-
return { entity };
|
|
97
|
-
}),
|
|
98
|
-
updateMemoryEntity: mock(
|
|
99
|
-
async (entityId: string, updates: Record<string, unknown>) => ({
|
|
100
|
-
entity: { id: entityId, ...updates },
|
|
101
|
-
}),
|
|
102
|
-
),
|
|
103
|
-
listMemoryEntities: mock(async () => ({
|
|
104
|
-
entities: [] as unknown[],
|
|
105
|
-
count: 0,
|
|
106
|
-
})),
|
|
107
|
-
searchMemoryEntities: mock(async () => ({
|
|
108
|
-
entities: [] as unknown[],
|
|
109
|
-
count: 0,
|
|
110
|
-
})),
|
|
111
|
-
getMemoryEntity: mock(async (id: string) => ({
|
|
112
|
-
entity: { id, type: "agent" },
|
|
113
|
-
})),
|
|
114
|
-
deleteMemoryEntity: mock(async () => ({ success: true })),
|
|
115
|
-
createMemoryRelation: mock(async () => ({ relation: {} })),
|
|
116
|
-
refreshAgentProfiles: mock(async () => ({ refreshed: true })),
|
|
117
|
-
getAgentProfile: mock(async () => ({
|
|
118
|
-
profile: {
|
|
119
|
-
agent_identifier: "claude-code",
|
|
120
|
-
total_sessions: 10,
|
|
121
|
-
completed_sessions: 8,
|
|
122
|
-
paused_sessions: 1,
|
|
123
|
-
blocked_sessions: 1,
|
|
124
|
-
completion_rate_pct: 80,
|
|
125
|
-
avg_active_duration_ms: 120000,
|
|
126
|
-
avg_completion_progress: 95,
|
|
127
|
-
first_session_at: "2026-01-01T00:00:00Z",
|
|
128
|
-
last_session_at: "2026-03-05T00:00:00Z",
|
|
129
|
-
},
|
|
130
|
-
})),
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function makeDeps(overrides: Partial<Record<string, unknown>> = {}) {
|
|
135
|
-
return {
|
|
136
|
-
getClient: () => null,
|
|
137
|
-
isConfigured: () => true,
|
|
138
|
-
getActiveProjectId: () => mockProjectId,
|
|
139
|
-
getActiveWorkspaceId: () =>
|
|
140
|
-
overrides.workspaceId !== undefined
|
|
141
|
-
? overrides.workspaceId
|
|
142
|
-
: mockWorkspaceId,
|
|
143
|
-
setActiveProject: () => {},
|
|
144
|
-
setActiveWorkspace: () => {},
|
|
145
|
-
getApiUrl: () => "http://localhost",
|
|
146
|
-
getMemoryDir: () => null,
|
|
147
|
-
getUserEmail: () => null,
|
|
148
|
-
saveConfig: () => {},
|
|
149
|
-
resetClient: () => {},
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// ============================================================
|
|
154
|
-
// Unit Tests
|
|
155
|
-
// ============================================================
|
|
156
|
-
|
|
157
|
-
describe("Agent profile refresh in runEndSessionPipeline", () => {
|
|
158
|
-
test("creates new entity when none exists", async () => {
|
|
159
|
-
const client = makeMockClient();
|
|
160
|
-
const deps = makeDeps();
|
|
161
|
-
|
|
162
|
-
await runEndSessionPipeline(
|
|
163
|
-
client as never,
|
|
164
|
-
deps as never,
|
|
165
|
-
"card-1",
|
|
166
|
-
"completed",
|
|
167
|
-
100,
|
|
168
|
-
{
|
|
169
|
-
agent_identifier: "claude-code",
|
|
170
|
-
agent_name: "Claude Code",
|
|
171
|
-
},
|
|
172
|
-
);
|
|
173
|
-
await flush();
|
|
174
|
-
|
|
175
|
-
expect(client.refreshAgentProfiles).toHaveBeenCalledWith(mockWorkspaceId);
|
|
176
|
-
expect(client.getAgentProfile).toHaveBeenCalled();
|
|
177
|
-
expect(client.createMemoryEntity).toHaveBeenCalled();
|
|
178
|
-
|
|
179
|
-
const agentEntity = client.createdEntities.find((e) => e.type === "agent");
|
|
180
|
-
expect(agentEntity).toBeTruthy();
|
|
181
|
-
expect(agentEntity!.memory_tier).toBe("reference");
|
|
182
|
-
expect(agentEntity!.confidence).toBe(1.0);
|
|
183
|
-
expect(agentEntity!.title).toBe("Agent Profile: claude-code");
|
|
184
|
-
expect(agentEntity!.tags as string[]).toContain("agent-profile");
|
|
185
|
-
expect(agentEntity!.tags as string[]).toContain("claude-code");
|
|
186
|
-
expect(agentEntity!.content as string).toContain(
|
|
187
|
-
"## claude-code Performance Profile",
|
|
188
|
-
);
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
test("updates existing entity by title match", async () => {
|
|
192
|
-
const client = makeMockClient();
|
|
193
|
-
client.listMemoryEntities = mock(async () => ({
|
|
194
|
-
entities: [
|
|
195
|
-
{
|
|
196
|
-
id: "existing-1",
|
|
197
|
-
title: "Agent Profile: claude-code",
|
|
198
|
-
agent_identifier: "claude-code",
|
|
199
|
-
},
|
|
200
|
-
],
|
|
201
|
-
count: 1,
|
|
202
|
-
}));
|
|
203
|
-
const deps = makeDeps();
|
|
204
|
-
|
|
205
|
-
await runEndSessionPipeline(
|
|
206
|
-
client as never,
|
|
207
|
-
deps as never,
|
|
208
|
-
"card-1",
|
|
209
|
-
"completed",
|
|
210
|
-
100,
|
|
211
|
-
{
|
|
212
|
-
agent_identifier: "claude-code",
|
|
213
|
-
agent_name: "Claude Code",
|
|
214
|
-
},
|
|
215
|
-
);
|
|
216
|
-
await flush();
|
|
217
|
-
|
|
218
|
-
expect(client.updateMemoryEntity).toHaveBeenCalledWith(
|
|
219
|
-
"existing-1",
|
|
220
|
-
expect.objectContaining({
|
|
221
|
-
content: expect.stringContaining("## claude-code Performance Profile"),
|
|
222
|
-
confidence: 1.0,
|
|
223
|
-
}),
|
|
224
|
-
);
|
|
225
|
-
// Should NOT create a new entity
|
|
226
|
-
const agentEntities = client.createdEntities.filter(
|
|
227
|
-
(e) => e.type === "agent",
|
|
228
|
-
);
|
|
229
|
-
expect(agentEntities).toHaveLength(0);
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
test("updates existing entity by agent_identifier match", async () => {
|
|
233
|
-
const client = makeMockClient();
|
|
234
|
-
client.listMemoryEntities = mock(async () => ({
|
|
235
|
-
entities: [
|
|
236
|
-
{
|
|
237
|
-
id: "existing-2",
|
|
238
|
-
title: "Old Title",
|
|
239
|
-
agent_identifier: "claude-code",
|
|
240
|
-
},
|
|
241
|
-
],
|
|
242
|
-
count: 1,
|
|
243
|
-
}));
|
|
244
|
-
const deps = makeDeps();
|
|
245
|
-
|
|
246
|
-
await runEndSessionPipeline(
|
|
247
|
-
client as never,
|
|
248
|
-
deps as never,
|
|
249
|
-
"card-1",
|
|
250
|
-
"completed",
|
|
251
|
-
100,
|
|
252
|
-
{
|
|
253
|
-
agent_identifier: "claude-code",
|
|
254
|
-
agent_name: "Claude Code",
|
|
255
|
-
},
|
|
256
|
-
);
|
|
257
|
-
await flush();
|
|
258
|
-
|
|
259
|
-
expect(client.updateMemoryEntity).toHaveBeenCalledWith(
|
|
260
|
-
"existing-2",
|
|
261
|
-
expect.objectContaining({
|
|
262
|
-
confidence: 1.0,
|
|
263
|
-
}),
|
|
264
|
-
);
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
test("skips when workspace is null", async () => {
|
|
268
|
-
const client = makeMockClient();
|
|
269
|
-
const deps = makeDeps({ workspaceId: null });
|
|
270
|
-
|
|
271
|
-
await runEndSessionPipeline(
|
|
272
|
-
client as never,
|
|
273
|
-
deps as never,
|
|
274
|
-
"card-1",
|
|
275
|
-
"completed",
|
|
276
|
-
100,
|
|
277
|
-
{
|
|
278
|
-
agent_identifier: "claude-code",
|
|
279
|
-
agent_name: "Claude Code",
|
|
280
|
-
},
|
|
281
|
-
);
|
|
282
|
-
await flush();
|
|
283
|
-
|
|
284
|
-
expect(client.refreshAgentProfiles).not.toHaveBeenCalled();
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
test('skips when agent is "unknown"', async () => {
|
|
288
|
-
const client = makeMockClient();
|
|
289
|
-
const deps = makeDeps();
|
|
290
|
-
|
|
291
|
-
await runEndSessionPipeline(
|
|
292
|
-
client as never,
|
|
293
|
-
deps as never,
|
|
294
|
-
"card-1",
|
|
295
|
-
"completed",
|
|
296
|
-
100,
|
|
297
|
-
{
|
|
298
|
-
agent_identifier: "unknown",
|
|
299
|
-
agent_name: "Unknown",
|
|
300
|
-
},
|
|
301
|
-
);
|
|
302
|
-
await flush();
|
|
303
|
-
|
|
304
|
-
expect(client.refreshAgentProfiles).not.toHaveBeenCalled();
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
test("skips when sessionData is undefined", async () => {
|
|
308
|
-
const client = makeMockClient();
|
|
309
|
-
const deps = makeDeps();
|
|
310
|
-
|
|
311
|
-
await runEndSessionPipeline(
|
|
312
|
-
client as never,
|
|
313
|
-
deps as never,
|
|
314
|
-
"card-1",
|
|
315
|
-
"completed",
|
|
316
|
-
100,
|
|
317
|
-
);
|
|
318
|
-
await flush();
|
|
319
|
-
|
|
320
|
-
// agent_identifier defaults to "unknown" when sessionData is undefined
|
|
321
|
-
expect(client.refreshAgentProfiles).not.toHaveBeenCalled();
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
test("non-fatal on refresh failure", async () => {
|
|
325
|
-
const client = makeMockClient();
|
|
326
|
-
client.refreshAgentProfiles = mock(async () => {
|
|
327
|
-
throw new Error("Refresh service down");
|
|
328
|
-
});
|
|
329
|
-
const deps = makeDeps();
|
|
330
|
-
|
|
331
|
-
// Should not throw
|
|
332
|
-
const result = await runEndSessionPipeline(
|
|
333
|
-
client as never,
|
|
334
|
-
deps as never,
|
|
335
|
-
"card-1",
|
|
336
|
-
"completed",
|
|
337
|
-
100,
|
|
338
|
-
{
|
|
339
|
-
agent_identifier: "claude-code",
|
|
340
|
-
agent_name: "Claude Code",
|
|
341
|
-
},
|
|
342
|
-
);
|
|
343
|
-
await flush();
|
|
344
|
-
|
|
345
|
-
// Pipeline still returns normally
|
|
346
|
-
expect(result).toBeTruthy();
|
|
347
|
-
expect(typeof result.learningsExtracted).toBe("number");
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
test("null profile skips entity upsert", async () => {
|
|
351
|
-
const client = makeMockClient();
|
|
352
|
-
client.getAgentProfile = mock(async () => ({ profile: null }));
|
|
353
|
-
const deps = makeDeps();
|
|
354
|
-
|
|
355
|
-
await runEndSessionPipeline(
|
|
356
|
-
client as never,
|
|
357
|
-
deps as never,
|
|
358
|
-
"card-1",
|
|
359
|
-
"completed",
|
|
360
|
-
100,
|
|
361
|
-
{
|
|
362
|
-
agent_identifier: "claude-code",
|
|
363
|
-
agent_name: "Claude Code",
|
|
364
|
-
},
|
|
365
|
-
);
|
|
366
|
-
await flush();
|
|
367
|
-
|
|
368
|
-
expect(client.refreshAgentProfiles).toHaveBeenCalled();
|
|
369
|
-
// No agent entity should be created since profile is null
|
|
370
|
-
const agentEntities = client.createdEntities.filter(
|
|
371
|
-
(e) => e.type === "agent",
|
|
372
|
-
);
|
|
373
|
-
expect(agentEntities).toHaveLength(0);
|
|
374
|
-
});
|
|
375
|
-
|
|
376
|
-
test("content has correct markdown", async () => {
|
|
377
|
-
const client = makeMockClient();
|
|
378
|
-
const deps = makeDeps();
|
|
379
|
-
|
|
380
|
-
await runEndSessionPipeline(
|
|
381
|
-
client as never,
|
|
382
|
-
deps as never,
|
|
383
|
-
"card-1",
|
|
384
|
-
"completed",
|
|
385
|
-
100,
|
|
386
|
-
{
|
|
387
|
-
agent_identifier: "claude-code",
|
|
388
|
-
agent_name: "Claude Code",
|
|
389
|
-
},
|
|
390
|
-
);
|
|
391
|
-
await flush();
|
|
392
|
-
|
|
393
|
-
const agentEntity = client.createdEntities.find((e) => e.type === "agent");
|
|
394
|
-
expect(agentEntity).toBeTruthy();
|
|
395
|
-
const content = agentEntity!.content as string;
|
|
396
|
-
expect(content).toContain("## claude-code Performance Profile");
|
|
397
|
-
expect(content).toContain("**Total sessions:**");
|
|
398
|
-
expect(content).toContain("**Completed:**");
|
|
399
|
-
expect(content).toContain("**Paused:**");
|
|
400
|
-
expect(content).toContain("**Blocked:**");
|
|
401
|
-
expect(content).toContain("**Avg duration:**");
|
|
402
|
-
expect(content).toContain("**First session:**");
|
|
403
|
-
expect(content).toContain("**Last session:**");
|
|
404
|
-
});
|
|
405
|
-
|
|
406
|
-
test("works with paused sessions", async () => {
|
|
407
|
-
const client = makeMockClient();
|
|
408
|
-
const deps = makeDeps();
|
|
409
|
-
|
|
410
|
-
await runEndSessionPipeline(
|
|
411
|
-
client as never,
|
|
412
|
-
deps as never,
|
|
413
|
-
"card-1",
|
|
414
|
-
"paused",
|
|
415
|
-
50,
|
|
416
|
-
{
|
|
417
|
-
agent_identifier: "claude-code",
|
|
418
|
-
agent_name: "Claude Code",
|
|
419
|
-
},
|
|
420
|
-
);
|
|
421
|
-
await flush();
|
|
422
|
-
|
|
423
|
-
expect(client.refreshAgentProfiles).toHaveBeenCalled();
|
|
424
|
-
expect(client.getAgentProfile).toHaveBeenCalled();
|
|
425
|
-
});
|
|
426
|
-
|
|
427
|
-
test("metadata contains profile data", async () => {
|
|
428
|
-
const client = makeMockClient();
|
|
429
|
-
const deps = makeDeps();
|
|
430
|
-
|
|
431
|
-
await runEndSessionPipeline(
|
|
432
|
-
client as never,
|
|
433
|
-
deps as never,
|
|
434
|
-
"card-1",
|
|
435
|
-
"completed",
|
|
436
|
-
100,
|
|
437
|
-
{
|
|
438
|
-
agent_identifier: "claude-code",
|
|
439
|
-
agent_name: "Claude Code",
|
|
440
|
-
},
|
|
441
|
-
);
|
|
442
|
-
await flush();
|
|
443
|
-
|
|
444
|
-
const agentEntity = client.createdEntities.find((e) => e.type === "agent");
|
|
445
|
-
expect(agentEntity).toBeTruthy();
|
|
446
|
-
const metadata = agentEntity!.metadata as Record<string, unknown>;
|
|
447
|
-
expect(metadata.total_sessions).toBe(10);
|
|
448
|
-
expect(metadata.completion_rate_pct).toBe(80);
|
|
449
|
-
expect(metadata.completed_sessions).toBe(8);
|
|
450
|
-
expect(metadata.avg_active_duration_ms).toBe(120000);
|
|
451
|
-
});
|
|
452
|
-
});
|
|
453
|
-
|
|
454
|
-
// ============================================================
|
|
455
|
-
// Integration Tests (skipped when not configured)
|
|
456
|
-
// ============================================================
|
|
457
|
-
|
|
458
|
-
// Integration tests are skipped in this file because mock.module() overrides
|
|
459
|
-
// the real config. Run integration-memory-crud.test.ts for live API tests,
|
|
460
|
-
// or use MCP tools directly for agent profile integration verification.
|
|
461
|
-
describe.skip("Agent Performance Profiles - Integration (run via MCP tools)", () => {
|
|
462
|
-
test("refreshAgentProfiles returns { refreshed: true }", () => {});
|
|
463
|
-
test('getAgentProfile("claude-code") returns profile or null', () => {});
|
|
464
|
-
test('getAgentProfile("non-existent-xyz") returns null profile', () => {});
|
|
465
|
-
test("listAgentProfiles returns array", () => {});
|
|
466
|
-
test("profile shape has expected fields", () => {});
|
|
467
|
-
test("entity round-trip: create agent entity → recall by type → cleanup", () => {});
|
|
468
|
-
});
|