@vellumai/assistant 0.4.49 → 0.4.50
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/ARCHITECTURE.md +24 -33
- package/README.md +3 -3
- package/docs/architecture/memory.md +180 -119
- package/package.json +2 -2
- package/src/__tests__/agent-loop.test.ts +3 -1
- package/src/__tests__/anthropic-provider.test.ts +114 -23
- package/src/__tests__/approval-cascade.test.ts +1 -15
- package/src/__tests__/approval-routes-http.test.ts +2 -0
- package/src/__tests__/assistant-feature-flag-guard.test.ts +0 -23
- package/src/__tests__/canonical-guardian-store.test.ts +95 -0
- package/src/__tests__/checker.test.ts +13 -0
- package/src/__tests__/config-schema.test.ts +1 -68
- package/src/__tests__/context-memory-e2e.test.ts +11 -100
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +8 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
- package/src/__tests__/credential-security-e2e.test.ts +1 -0
- package/src/__tests__/credential-vault-unit.test.ts +4 -0
- package/src/__tests__/credential-vault.test.ts +13 -1
- package/src/__tests__/cu-unified-flow.test.ts +532 -0
- package/src/__tests__/date-context.test.ts +93 -77
- package/src/__tests__/deterministic-verification-control-plane.test.ts +64 -0
- package/src/__tests__/guardian-routing-invariants.test.ts +93 -0
- package/src/__tests__/history-repair.test.ts +245 -0
- package/src/__tests__/host-cu-proxy.test.ts +165 -3
- package/src/__tests__/http-user-message-parity.test.ts +1 -0
- package/src/__tests__/invite-redemption-service.test.ts +65 -1
- package/src/__tests__/keychain-broker-client.test.ts +4 -4
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +56 -18
- package/src/__tests__/memory-lifecycle-e2e.test.ts +244 -387
- package/src/__tests__/memory-recall-quality.test.ts +244 -407
- package/src/__tests__/memory-regressions.experimental.test.ts +126 -101
- package/src/__tests__/memory-regressions.test.ts +477 -2841
- package/src/__tests__/memory-retrieval.benchmark.test.ts +33 -150
- package/src/__tests__/memory-upsert-concurrency.test.ts +5 -244
- package/src/__tests__/mime-builder.test.ts +28 -0
- package/src/__tests__/native-web-search.test.ts +1 -0
- package/src/__tests__/oauth-cli.test.ts +572 -5
- package/src/__tests__/oauth-store.test.ts +120 -6
- package/src/__tests__/qdrant-collection-migration.test.ts +53 -8
- package/src/__tests__/registry.test.ts +0 -1
- package/src/__tests__/relay-server.test.ts +46 -1
- package/src/__tests__/schedule-tools.test.ts +32 -0
- package/src/__tests__/script-proxy-certs.test.ts +1 -1
- package/src/__tests__/secret-onetime-send.test.ts +1 -0
- package/src/__tests__/secure-keys.test.ts +7 -2
- package/src/__tests__/send-endpoint-busy.test.ts +3 -0
- package/src/__tests__/session-abort-tool-results.test.ts +1 -14
- package/src/__tests__/session-agent-loop-overflow.test.ts +1583 -0
- package/src/__tests__/session-agent-loop.test.ts +19 -15
- package/src/__tests__/session-confirmation-signals.test.ts +1 -15
- package/src/__tests__/session-error.test.ts +124 -2
- package/src/__tests__/session-history-web-search.test.ts +918 -0
- package/src/__tests__/session-pre-run-repair.test.ts +1 -14
- package/src/__tests__/session-provider-retry-repair.test.ts +25 -28
- package/src/__tests__/session-queue.test.ts +37 -27
- package/src/__tests__/session-runtime-assembly.test.ts +54 -0
- package/src/__tests__/session-slash-known.test.ts +1 -15
- package/src/__tests__/session-slash-queue.test.ts +1 -15
- package/src/__tests__/session-slash-unknown.test.ts +1 -15
- package/src/__tests__/session-workspace-cache-state.test.ts +3 -33
- package/src/__tests__/session-workspace-injection.test.ts +3 -37
- package/src/__tests__/session-workspace-tool-tracking.test.ts +3 -37
- package/src/__tests__/skills-install-extract.test.ts +93 -0
- package/src/__tests__/skillssh-registry.test.ts +451 -0
- package/src/__tests__/trust-store.test.ts +15 -0
- package/src/__tests__/voice-invite-redemption.test.ts +32 -1
- package/src/agent/ax-tree-compaction.test.ts +51 -0
- package/src/agent/loop.ts +39 -12
- package/src/approvals/AGENTS.md +1 -1
- package/src/approvals/guardian-request-resolvers.ts +14 -2
- package/src/bundler/compiler-tools.ts +66 -2
- package/src/calls/call-domain.ts +132 -0
- package/src/calls/call-store.ts +6 -0
- package/src/calls/relay-server.ts +43 -5
- package/src/calls/relay-setup-router.ts +17 -1
- package/src/calls/twilio-config.ts +1 -1
- package/src/calls/types.ts +3 -1
- package/src/cli/commands/doctor.ts +4 -3
- package/src/cli/commands/mcp.ts +46 -59
- package/src/cli/commands/memory.ts +16 -165
- package/src/cli/commands/oauth/apps.ts +31 -2
- package/src/cli/commands/oauth/connections.ts +431 -97
- package/src/cli/commands/oauth/providers.ts +15 -1
- package/src/cli/commands/sessions.ts +5 -2
- package/src/cli/commands/skills.ts +173 -1
- package/src/cli/http-client.ts +0 -20
- package/src/cli/main-screen.tsx +2 -2
- package/src/cli/program.ts +5 -6
- package/src/cli.ts +4 -10
- package/src/config/bundled-skills/computer-use/TOOLS.json +1 -1
- package/src/config/bundled-skills/computer-use/tools/computer-use-observe.ts +12 -0
- package/src/config/bundled-tool-registry.ts +2 -5
- package/src/config/schema.ts +1 -12
- package/src/config/schemas/memory-lifecycle.ts +0 -9
- package/src/config/schemas/memory-processing.ts +0 -180
- package/src/config/schemas/memory-retrieval.ts +32 -104
- package/src/config/schemas/memory.ts +0 -10
- package/src/config/types.ts +0 -4
- package/src/context/window-manager.ts +4 -1
- package/src/daemon/config-watcher.ts +61 -3
- package/src/daemon/daemon-control.ts +1 -1
- package/src/daemon/date-context.ts +114 -31
- package/src/daemon/handlers/sessions.ts +18 -13
- package/src/daemon/handlers/skills.ts +20 -1
- package/src/daemon/history-repair.ts +72 -8
- package/src/daemon/host-cu-proxy.ts +55 -26
- package/src/daemon/lifecycle.ts +31 -3
- package/src/daemon/mcp-reload-service.ts +2 -2
- package/src/daemon/message-types/computer-use.ts +1 -12
- package/src/daemon/message-types/memory.ts +4 -16
- package/src/daemon/message-types/messages.ts +1 -0
- package/src/daemon/message-types/sessions.ts +4 -0
- package/src/daemon/server.ts +12 -1
- package/src/daemon/session-agent-loop-handlers.ts +38 -0
- package/src/daemon/session-agent-loop.ts +334 -48
- package/src/daemon/session-error.ts +89 -6
- package/src/daemon/session-history.ts +17 -7
- package/src/daemon/session-media-retry.ts +6 -2
- package/src/daemon/session-memory.ts +69 -149
- package/src/daemon/session-process.ts +10 -1
- package/src/daemon/session-runtime-assembly.ts +49 -19
- package/src/daemon/session-surfaces.ts +4 -1
- package/src/daemon/session-tool-setup.ts +7 -1
- package/src/daemon/session.ts +12 -2
- package/src/instrument.ts +61 -1
- package/src/memory/admin.ts +2 -191
- package/src/memory/canonical-guardian-store.ts +38 -2
- package/src/memory/conversation-crud.ts +0 -33
- package/src/memory/conversation-queries.ts +22 -3
- package/src/memory/db-init.ts +28 -0
- package/src/memory/embedding-backend.ts +84 -8
- package/src/memory/embedding-types.ts +9 -1
- package/src/memory/indexer.ts +7 -46
- package/src/memory/items-extractor.ts +274 -76
- package/src/memory/job-handlers/backfill.ts +2 -127
- package/src/memory/job-handlers/cleanup.ts +2 -16
- package/src/memory/job-handlers/extraction.ts +2 -138
- package/src/memory/job-handlers/index-maintenance.ts +1 -6
- package/src/memory/job-handlers/summarization.ts +3 -148
- package/src/memory/job-utils.ts +21 -59
- package/src/memory/jobs-store.ts +1 -159
- package/src/memory/jobs-worker.ts +9 -52
- package/src/memory/migrations/104-core-indexes.ts +3 -3
- package/src/memory/migrations/149-oauth-tables.ts +2 -0
- package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +98 -0
- package/src/memory/migrations/151-oauth-providers-ping-url.ts +11 -0
- package/src/memory/migrations/152-memory-item-supersession.ts +44 -0
- package/src/memory/migrations/153-drop-entity-tables.ts +15 -0
- package/src/memory/migrations/154-drop-fts.ts +20 -0
- package/src/memory/migrations/155-drop-conflicts.ts +7 -0
- package/src/memory/migrations/156-call-session-invite-metadata.ts +24 -0
- package/src/memory/migrations/index.ts +7 -0
- package/src/memory/qdrant-client.ts +148 -51
- package/src/memory/raw-query.ts +1 -1
- package/src/memory/retriever.test.ts +294 -273
- package/src/memory/retriever.ts +421 -645
- package/src/memory/schema/calls.ts +2 -0
- package/src/memory/schema/memory-core.ts +3 -48
- package/src/memory/schema/oauth.ts +2 -0
- package/src/memory/search/formatting.ts +263 -176
- package/src/memory/search/lexical.ts +1 -254
- package/src/memory/search/ranking.ts +0 -455
- package/src/memory/search/semantic.ts +100 -14
- package/src/memory/search/staleness.ts +47 -0
- package/src/memory/search/tier-classifier.ts +21 -0
- package/src/memory/search/types.ts +15 -77
- package/src/memory/task-memory-cleanup.ts +4 -6
- package/src/messaging/providers/gmail/mime-builder.ts +17 -7
- package/src/oauth/byo-connection.test.ts +8 -1
- package/src/oauth/oauth-store.ts +113 -27
- package/src/oauth/seed-providers.ts +6 -0
- package/src/oauth/token-persistence.ts +11 -3
- package/src/permissions/defaults.ts +1 -0
- package/src/permissions/trust-store.ts +23 -1
- package/src/playbooks/playbook-compiler.ts +1 -1
- package/src/prompts/system-prompt.ts +18 -2
- package/src/providers/anthropic/client.ts +56 -126
- package/src/providers/types.ts +7 -1
- package/src/runtime/AGENTS.md +9 -0
- package/src/runtime/auth/route-policy.ts +6 -3
- package/src/runtime/guardian-reply-router.ts +24 -22
- package/src/runtime/http-server.ts +2 -2
- package/src/runtime/invite-redemption-service.ts +19 -1
- package/src/runtime/invite-service.ts +25 -0
- package/src/runtime/pending-interactions.ts +2 -2
- package/src/runtime/routes/brain-graph-routes.ts +10 -90
- package/src/runtime/routes/conversation-routes.ts +9 -1
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +21 -12
- package/src/runtime/routes/memory-item-routes.test.ts +754 -0
- package/src/runtime/routes/memory-item-routes.ts +503 -0
- package/src/runtime/routes/session-management-routes.ts +3 -3
- package/src/runtime/routes/settings-routes.ts +2 -2
- package/src/runtime/routes/trust-rules-routes.ts +14 -0
- package/src/runtime/routes/workspace-routes.ts +2 -1
- package/src/security/keychain-broker-client.ts +17 -4
- package/src/security/secure-keys.ts +25 -3
- package/src/security/token-manager.ts +36 -36
- package/src/skills/catalog-install.ts +74 -18
- package/src/skills/skillssh-registry.ts +503 -0
- package/src/tools/assets/search.ts +5 -1
- package/src/tools/computer-use/definitions.ts +0 -10
- package/src/tools/computer-use/registry.ts +1 -1
- package/src/tools/credentials/vault.ts +1 -3
- package/src/tools/memory/definitions.ts +4 -13
- package/src/tools/memory/handlers.test.ts +83 -103
- package/src/tools/memory/handlers.ts +50 -85
- package/src/tools/schedule/create.ts +8 -1
- package/src/tools/schedule/update.ts +8 -1
- package/src/tools/skills/load.ts +25 -2
- package/src/__tests__/clarification-resolver.test.ts +0 -193
- package/src/__tests__/conflict-intent-tokenization.test.ts +0 -160
- package/src/__tests__/conflict-policy.test.ts +0 -269
- package/src/__tests__/conflict-store.test.ts +0 -372
- package/src/__tests__/contradiction-checker.test.ts +0 -361
- package/src/__tests__/entity-extractor.test.ts +0 -211
- package/src/__tests__/entity-search.test.ts +0 -1117
- package/src/__tests__/profile-compiler.test.ts +0 -392
- package/src/__tests__/session-conflict-gate.test.ts +0 -1228
- package/src/__tests__/session-profile-injection.test.ts +0 -557
- package/src/config/bundled-skills/knowledge-graph/SKILL.md +0 -25
- package/src/config/bundled-skills/knowledge-graph/TOOLS.json +0 -66
- package/src/config/bundled-skills/knowledge-graph/tools/graph-query.ts +0 -211
- package/src/daemon/session-conflict-gate.ts +0 -167
- package/src/daemon/session-dynamic-profile.ts +0 -77
- package/src/memory/clarification-resolver.ts +0 -417
- package/src/memory/conflict-intent.ts +0 -205
- package/src/memory/conflict-policy.ts +0 -127
- package/src/memory/conflict-store.ts +0 -410
- package/src/memory/contradiction-checker.ts +0 -508
- package/src/memory/entity-extractor.ts +0 -535
- package/src/memory/format-recall.ts +0 -47
- package/src/memory/fts-reconciler.ts +0 -165
- package/src/memory/job-handlers/conflict.ts +0 -200
- package/src/memory/profile-compiler.ts +0 -195
- package/src/memory/recall-cache.ts +0 -117
- package/src/memory/search/entity.ts +0 -535
- package/src/memory/search/query-expansion.test.ts +0 -70
- package/src/memory/search/query-expansion.ts +0 -118
- package/src/runtime/routes/mcp-routes.ts +0 -20
|
@@ -31,6 +31,23 @@ mock.module("../util/logger.js", () => ({
|
|
|
31
31
|
}),
|
|
32
32
|
}));
|
|
33
33
|
|
|
34
|
+
// Dynamic Qdrant mock: tests can push results to be returned by searchWithFilter/hybridSearch
|
|
35
|
+
let mockQdrantResults: Array<{
|
|
36
|
+
id: string;
|
|
37
|
+
score: number;
|
|
38
|
+
payload: Record<string, unknown>;
|
|
39
|
+
}> = [];
|
|
40
|
+
|
|
41
|
+
mock.module("../memory/qdrant-client.js", () => ({
|
|
42
|
+
getQdrantClient: () => ({
|
|
43
|
+
searchWithFilter: async () => mockQdrantResults,
|
|
44
|
+
hybridSearch: async () => mockQdrantResults,
|
|
45
|
+
upsert: async () => {},
|
|
46
|
+
deletePoints: async () => {},
|
|
47
|
+
}),
|
|
48
|
+
initQdrantClient: () => {},
|
|
49
|
+
}));
|
|
50
|
+
|
|
34
51
|
import { eq } from "drizzle-orm";
|
|
35
52
|
|
|
36
53
|
import { DEFAULT_CONFIG } from "../config/defaults.js";
|
|
@@ -55,7 +72,6 @@ mock.module("../config/loader.js", () => ({
|
|
|
55
72
|
}));
|
|
56
73
|
import { getDb, initializeDb, resetDb } from "../memory/db.js";
|
|
57
74
|
import { indexMessageNow } from "../memory/indexer.js";
|
|
58
|
-
import { vectorToBlob } from "../memory/job-utils.js";
|
|
59
75
|
import { enqueueMemoryJob } from "../memory/jobs-store.js";
|
|
60
76
|
import {
|
|
61
77
|
resetCleanupScheduleThrottle,
|
|
@@ -65,7 +81,6 @@ import {
|
|
|
65
81
|
import { buildMemoryRecall } from "../memory/retriever.js";
|
|
66
82
|
import {
|
|
67
83
|
conversations,
|
|
68
|
-
memoryEmbeddings,
|
|
69
84
|
memoryItems,
|
|
70
85
|
memoryItemSources,
|
|
71
86
|
memoryJobs,
|
|
@@ -80,15 +95,11 @@ describe("Memory regressions (experimental)", () => {
|
|
|
80
95
|
|
|
81
96
|
beforeEach(() => {
|
|
82
97
|
const db = getDb();
|
|
83
|
-
db.run("DELETE FROM memory_item_conflicts");
|
|
84
|
-
db.run("DELETE FROM memory_item_entities");
|
|
85
|
-
db.run("DELETE FROM memory_entity_relations");
|
|
86
|
-
db.run("DELETE FROM memory_entities");
|
|
87
98
|
db.run("DELETE FROM memory_item_sources");
|
|
88
99
|
db.run("DELETE FROM memory_embeddings");
|
|
89
|
-
db.run("DELETE FROM memory_summaries");
|
|
90
100
|
db.run("DELETE FROM memory_items");
|
|
91
|
-
|
|
101
|
+
|
|
102
|
+
db.run("DELETE FROM memory_summaries");
|
|
92
103
|
db.run("DELETE FROM memory_segments");
|
|
93
104
|
db.run("DELETE FROM messages");
|
|
94
105
|
db.run("DELETE FROM conversations");
|
|
@@ -96,6 +107,7 @@ describe("Memory regressions (experimental)", () => {
|
|
|
96
107
|
db.run("DELETE FROM memory_checkpoints");
|
|
97
108
|
resetCleanupScheduleThrottle();
|
|
98
109
|
resetStaleSweepThrottle();
|
|
110
|
+
mockQdrantResults = [];
|
|
99
111
|
});
|
|
100
112
|
|
|
101
113
|
afterAll(() => {
|
|
@@ -111,8 +123,11 @@ describe("Memory regressions (experimental)", () => {
|
|
|
111
123
|
run: () => Promise<T>,
|
|
112
124
|
): Promise<T> {
|
|
113
125
|
const originalFetch = globalThis.fetch;
|
|
126
|
+
// Return 384-dim vectors to match the Qdrant collection's expected size
|
|
127
|
+
const mockVector = new Array(384).fill(0);
|
|
128
|
+
mockVector[0] = 1;
|
|
114
129
|
globalThis.fetch = (async () =>
|
|
115
|
-
new Response(JSON.stringify({ data: [{ embedding:
|
|
130
|
+
new Response(JSON.stringify({ data: [{ embedding: mockVector }] }), {
|
|
116
131
|
status: 200,
|
|
117
132
|
headers: { "content-type": "application/json" },
|
|
118
133
|
})) as unknown as typeof globalThis.fetch;
|
|
@@ -135,8 +150,6 @@ describe("Memory regressions (experimental)", () => {
|
|
|
135
150
|
},
|
|
136
151
|
retrieval: {
|
|
137
152
|
...DEFAULT_CONFIG.memory.retrieval,
|
|
138
|
-
lexicalTopK: 0,
|
|
139
|
-
semanticTopK: 10,
|
|
140
153
|
maxInjectTokens: 2000,
|
|
141
154
|
},
|
|
142
155
|
},
|
|
@@ -184,7 +197,7 @@ describe("Memory regressions (experimental)", () => {
|
|
|
184
197
|
.values([
|
|
185
198
|
{
|
|
186
199
|
id: "item-semantic-old",
|
|
187
|
-
kind: "
|
|
200
|
+
kind: "identity",
|
|
188
201
|
subject: "timezone",
|
|
189
202
|
statement: "User timezone is PST",
|
|
190
203
|
status: "active",
|
|
@@ -196,7 +209,7 @@ describe("Memory regressions (experimental)", () => {
|
|
|
196
209
|
},
|
|
197
210
|
{
|
|
198
211
|
id: "item-semantic-current",
|
|
199
|
-
kind: "
|
|
212
|
+
kind: "identity",
|
|
200
213
|
subject: "timezone",
|
|
201
214
|
statement: "User timezone is PST (current turn)",
|
|
202
215
|
status: "active",
|
|
@@ -224,32 +237,35 @@ describe("Memory regressions (experimental)", () => {
|
|
|
224
237
|
},
|
|
225
238
|
])
|
|
226
239
|
.run();
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
240
|
+
// Mock Qdrant to return both items as search results
|
|
241
|
+
mockQdrantResults = [
|
|
242
|
+
{
|
|
243
|
+
id: "emb-semantic-old",
|
|
244
|
+
score: 0.95,
|
|
245
|
+
payload: {
|
|
246
|
+
target_type: "item",
|
|
247
|
+
target_id: "item-semantic-old",
|
|
248
|
+
text: "User timezone is PST",
|
|
249
|
+
kind: "identity",
|
|
250
|
+
status: "active",
|
|
251
|
+
created_at: now - 10_000,
|
|
252
|
+
last_seen_at: now - 10_000,
|
|
239
253
|
},
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
id: "emb-semantic-current",
|
|
257
|
+
score: 0.93,
|
|
258
|
+
payload: {
|
|
259
|
+
target_type: "item",
|
|
260
|
+
target_id: "item-semantic-current",
|
|
261
|
+
text: "User timezone is PST (current turn)",
|
|
262
|
+
kind: "identity",
|
|
263
|
+
status: "active",
|
|
264
|
+
created_at: now,
|
|
265
|
+
last_seen_at: now,
|
|
250
266
|
},
|
|
251
|
-
|
|
252
|
-
|
|
267
|
+
},
|
|
268
|
+
];
|
|
253
269
|
|
|
254
270
|
const recall = await withMockOllamaQueryEmbedding(() =>
|
|
255
271
|
buildMemoryRecall(
|
|
@@ -294,7 +310,7 @@ describe("Memory regressions (experimental)", () => {
|
|
|
294
310
|
.values([
|
|
295
311
|
{
|
|
296
312
|
id: "item-semantic-with-evidence",
|
|
297
|
-
kind: "
|
|
313
|
+
kind: "identity",
|
|
298
314
|
subject: "timezone",
|
|
299
315
|
statement: "User timezone is PST",
|
|
300
316
|
status: "active",
|
|
@@ -306,7 +322,7 @@ describe("Memory regressions (experimental)", () => {
|
|
|
306
322
|
},
|
|
307
323
|
{
|
|
308
324
|
id: "item-semantic-orphan",
|
|
309
|
-
kind: "
|
|
325
|
+
kind: "identity",
|
|
310
326
|
subject: "timezone",
|
|
311
327
|
statement: "Stale orphan fact",
|
|
312
328
|
status: "active",
|
|
@@ -326,32 +342,35 @@ describe("Memory regressions (experimental)", () => {
|
|
|
326
342
|
createdAt: now,
|
|
327
343
|
})
|
|
328
344
|
.run();
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
345
|
+
// Mock Qdrant to return both items as search results
|
|
346
|
+
mockQdrantResults = [
|
|
347
|
+
{
|
|
348
|
+
id: "emb-semantic-with-evidence",
|
|
349
|
+
score: 0.95,
|
|
350
|
+
payload: {
|
|
351
|
+
target_type: "item",
|
|
352
|
+
target_id: "item-semantic-with-evidence",
|
|
353
|
+
text: "User timezone is PST",
|
|
354
|
+
kind: "identity",
|
|
355
|
+
status: "active",
|
|
356
|
+
created_at: now,
|
|
357
|
+
last_seen_at: now,
|
|
341
358
|
},
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
id: "emb-semantic-orphan",
|
|
362
|
+
score: 0.9,
|
|
363
|
+
payload: {
|
|
364
|
+
target_type: "item",
|
|
365
|
+
target_id: "item-semantic-orphan",
|
|
366
|
+
text: "Stale orphan fact",
|
|
367
|
+
kind: "identity",
|
|
368
|
+
status: "active",
|
|
369
|
+
created_at: now,
|
|
370
|
+
last_seen_at: now,
|
|
352
371
|
},
|
|
353
|
-
|
|
354
|
-
|
|
372
|
+
},
|
|
373
|
+
];
|
|
355
374
|
|
|
356
375
|
const recall = await withMockOllamaQueryEmbedding(() =>
|
|
357
376
|
buildMemoryRecall(
|
|
@@ -420,48 +439,51 @@ describe("Memory regressions (experimental)", () => {
|
|
|
420
439
|
},
|
|
421
440
|
])
|
|
422
441
|
.run();
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
442
|
+
// Mock Qdrant to return both summaries as search results.
|
|
443
|
+
// The new pipeline does not exclude conversation summaries based on
|
|
444
|
+
// time overlap with excluded messages — that was old-pipeline behavior.
|
|
445
|
+
// Both summaries pass through; we verify the pipeline runs correctly.
|
|
446
|
+
mockQdrantResults = [
|
|
447
|
+
{
|
|
448
|
+
id: "emb-summary-semantic-conversation",
|
|
449
|
+
score: 0.95,
|
|
450
|
+
payload: {
|
|
451
|
+
target_type: "summary",
|
|
452
|
+
target_id: "summary-semantic-conversation",
|
|
453
|
+
text: "[conversation] Conversation summary containing current turn details",
|
|
454
|
+
kind: "conversation",
|
|
455
|
+
created_at: now,
|
|
456
|
+
last_seen_at: now,
|
|
435
457
|
},
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
id: "emb-summary-semantic-weekly",
|
|
461
|
+
score: 0.9,
|
|
462
|
+
payload: {
|
|
463
|
+
target_type: "summary",
|
|
464
|
+
target_id: "summary-semantic-weekly",
|
|
465
|
+
text: "[weekly_global] Weekly summary that should remain eligible",
|
|
466
|
+
kind: "global",
|
|
467
|
+
created_at: now,
|
|
468
|
+
last_seen_at: now,
|
|
446
469
|
},
|
|
447
|
-
|
|
448
|
-
|
|
470
|
+
},
|
|
471
|
+
];
|
|
449
472
|
|
|
450
473
|
const recall = await withMockOllamaQueryEmbedding(() =>
|
|
451
474
|
buildMemoryRecall("summary", conversationId, semanticRecallConfig(), {
|
|
452
475
|
excludeMessageIds: ["msg-semantic-summary-excluded"],
|
|
453
476
|
}),
|
|
454
477
|
);
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
);
|
|
478
|
+
// Both summaries are returned from Qdrant and both pass post-filtering.
|
|
479
|
+
// Verify the pipeline completes successfully with semantic hits.
|
|
480
|
+
expect(recall.semanticHits).toBe(2);
|
|
459
481
|
expect(recall.injectedText).toContain(
|
|
460
482
|
"Weekly summary that should remain eligible",
|
|
461
483
|
);
|
|
462
484
|
});
|
|
463
485
|
|
|
464
|
-
test("indexing
|
|
486
|
+
test("indexing enqueues embed_segment, extract_items, and build_conversation_summary for user messages", () => {
|
|
465
487
|
const db = getDb();
|
|
466
488
|
const createdAt = 2_000;
|
|
467
489
|
db.insert(conversations)
|
|
@@ -502,14 +524,15 @@ describe("Memory regressions (experimental)", () => {
|
|
|
502
524
|
},
|
|
503
525
|
DEFAULT_CONFIG.memory,
|
|
504
526
|
);
|
|
505
|
-
|
|
527
|
+
// embed_segment (1 segment) + extract_items + build_conversation_summary = 3
|
|
528
|
+
expect(result.enqueuedJobs).toBe(3);
|
|
506
529
|
|
|
507
530
|
const embedSegmentJobs = db
|
|
508
531
|
.select()
|
|
509
532
|
.from(memoryJobs)
|
|
510
533
|
.where(eq(memoryJobs.type, "embed_segment"))
|
|
511
534
|
.all();
|
|
512
|
-
expect(embedSegmentJobs).toHaveLength(
|
|
535
|
+
expect(embedSegmentJobs).toHaveLength(1);
|
|
513
536
|
});
|
|
514
537
|
|
|
515
538
|
test("indexing skips durable item extraction for assistant messages when extractFromAssistant is false", () => {
|
|
@@ -561,7 +584,9 @@ describe("Memory regressions (experimental)", () => {
|
|
|
561
584
|
},
|
|
562
585
|
memoryConfig,
|
|
563
586
|
);
|
|
564
|
-
|
|
587
|
+
// embed_segment (1 segment) + build_conversation_summary = 2
|
|
588
|
+
// (extract_items is skipped for assistant messages when extractFromAssistant=false)
|
|
589
|
+
expect(result.enqueuedJobs).toBe(2);
|
|
565
590
|
|
|
566
591
|
const extractionJobs = db
|
|
567
592
|
.select()
|
|
@@ -571,24 +596,24 @@ describe("Memory regressions (experimental)", () => {
|
|
|
571
596
|
expect(extractionJobs).toHaveLength(0);
|
|
572
597
|
});
|
|
573
598
|
|
|
574
|
-
test("embed jobs
|
|
599
|
+
test("embed jobs complete successfully when backend and Qdrant mock are available", async () => {
|
|
575
600
|
const db = getDb();
|
|
576
601
|
const now = 3_000;
|
|
577
602
|
db.insert(memoryItems)
|
|
578
603
|
.values({
|
|
579
|
-
id: "item-
|
|
580
|
-
kind: "
|
|
604
|
+
id: "item-embed-test",
|
|
605
|
+
kind: "identity",
|
|
581
606
|
subject: "backend",
|
|
582
|
-
statement: "
|
|
607
|
+
statement: "Embedding pipeline test item",
|
|
583
608
|
status: "active",
|
|
584
609
|
confidence: 0.8,
|
|
585
|
-
fingerprint: "item-
|
|
610
|
+
fingerprint: "item-embed-test-fingerprint",
|
|
586
611
|
firstSeenAt: now,
|
|
587
612
|
lastSeenAt: now,
|
|
588
613
|
lastUsedAt: null,
|
|
589
614
|
})
|
|
590
615
|
.run();
|
|
591
|
-
const jobId = enqueueMemoryJob("embed_item", { itemId: "item-
|
|
616
|
+
const jobId = enqueueMemoryJob("embed_item", { itemId: "item-embed-test" });
|
|
592
617
|
|
|
593
618
|
const processed = await runMemoryJobsOnce();
|
|
594
619
|
expect(processed).toBe(1);
|