clementine-agent 1.1.31 → 1.2.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/dist/agent/assistant.js +52 -7
- package/dist/cli/dashboard.js +601 -7
- package/dist/cli/index.js +79 -1
- package/dist/memory/consolidation.d.ts +1 -1
- package/dist/memory/consolidation.js +2 -2
- package/dist/memory/context-assembler.d.ts +2 -0
- package/dist/memory/context-assembler.js +14 -0
- package/dist/memory/embeddings.d.ts +36 -5
- package/dist/memory/embeddings.js +118 -5
- package/dist/memory/store.d.ts +206 -1
- package/dist/memory/store.js +673 -37
- package/dist/tools/memory-tools.js +72 -0
- package/dist/tools/shared.d.ts +151 -0
- package/package.json +2 -1
package/dist/agent/assistant.js
CHANGED
|
@@ -24,6 +24,7 @@ import { StallGuard } from './stall-guard.js';
|
|
|
24
24
|
import { collectToolCalls, detectContradiction, buildCorrectionPrompt } from './contradiction-validator.js';
|
|
25
25
|
import { recordToolOutcome as recordMcpToolOutcome } from './mcp-circuit-breaker.js';
|
|
26
26
|
import { assembleContext } from '../memory/context-assembler.js';
|
|
27
|
+
import * as embeddingsModule from '../memory/embeddings.js';
|
|
27
28
|
import { PromptCache } from './prompt-cache.js';
|
|
28
29
|
import { searchSkills as searchSkillsSync } from './skill-extractor.js';
|
|
29
30
|
import { classifyIntent, getStrategyGuidance } from './intent-classifier.js';
|
|
@@ -378,13 +379,23 @@ const AUTO_MEMORY_PROMPT = `You are a memory extraction agent. Your ONLY job is
|
|
|
378
379
|
|
|
379
380
|
{current_memory}
|
|
380
381
|
|
|
381
|
-
##
|
|
382
|
-
|
|
382
|
+
## Where to save what (memory routing):
|
|
383
|
+
|
|
384
|
+
**Always-in-context core memory** (use the user_model tool — these stay top-of-mind in every future session):
|
|
385
|
+
- **Lasting facts about ${OWNER}** (role, location, identifiers, durable preferences, communication style) → user_model(action="append", slot="user_facts", content=...)
|
|
386
|
+
- **Active goals/intents** (what ${OWNER} is trying to accomplish right now) → user_model(action="append", slot="goals", content=...)
|
|
387
|
+
- **Key people/projects** (recurring relationships) → user_model(action="append", slot="relationships", content=...)
|
|
388
|
+
- Use action="replace" instead of "append" if you're updating an existing fact rather than adding a new one. Slots are capped at 2000 chars — older content rolls off on append.
|
|
389
|
+
|
|
390
|
+
**Vault notes** (use memory_write/note_create — durable but retrieved on demand):
|
|
383
391
|
- **People mentioned** — names, relationships, context → create or update person notes in 02-People/
|
|
384
392
|
- **Projects/work** — project names, status updates, decisions → update relevant project notes
|
|
385
|
-
- **
|
|
386
|
-
- **
|
|
387
|
-
|
|
393
|
+
- **Dates/events** — meetings, deadlines, appointments → note in daily log
|
|
394
|
+
- **Specific episodes** — "on Tuesday we discussed X" → memory_write(action="append_daily")
|
|
395
|
+
|
|
396
|
+
**Tasks** — anything ${OWNER} asked to be done later → task_add
|
|
397
|
+
|
|
398
|
+
Routing rule: if the fact is something the agent should *always know* (not just "find when relevant"), it belongs in user_model. Episodic events and topical knowledge belong in the vault.
|
|
388
399
|
|
|
389
400
|
## What to skip:
|
|
390
401
|
- Greetings, small talk, "thanks", "ok"
|
|
@@ -401,7 +412,7 @@ const AUTO_MEMORY_PROMPT = `You are a memory extraction agent. Your ONLY job is
|
|
|
401
412
|
- Only save genuinely NEW facts not already present in the Current Memory above.
|
|
402
413
|
- If updating an existing topic, use memory_write(action="update_memory") to REPLACE the section, not append duplicates.
|
|
403
414
|
- If there's nothing new to save, respond "No new facts." and exit — do NOT call any tools.
|
|
404
|
-
- Use the MCP tools (memory_write, note_create, task_add, note_take).
|
|
415
|
+
- Use the MCP tools (user_model, memory_write, note_create, task_add, note_take).
|
|
405
416
|
- NEVER respond to ${OWNER}. You are invisible. Just save facts and exit.
|
|
406
417
|
|
|
407
418
|
## Behavioral Correction Detection:
|
|
@@ -1963,7 +1974,27 @@ You have a cost budget per message — not a hard turn limit. Work until the tas
|
|
|
1963
1974
|
if (enrichedQuery.length > 1000) {
|
|
1964
1975
|
enrichedQuery = enrichedQuery.slice(0, 1000);
|
|
1965
1976
|
}
|
|
1966
|
-
|
|
1977
|
+
// Pre-compute dense query embedding if the model is ready. Done outside
|
|
1978
|
+
// searchContext (which is sync) so the dense path doesn't force the
|
|
1979
|
+
// entire call chain to be async. If embedDense fails or isn't available,
|
|
1980
|
+
// searchContext falls back to TF-IDF.
|
|
1981
|
+
let queryDenseVec;
|
|
1982
|
+
try {
|
|
1983
|
+
if (embeddingsModule.isDenseReady()) {
|
|
1984
|
+
const v = await embeddingsModule.embedDense(enrichedQuery, true);
|
|
1985
|
+
if (v)
|
|
1986
|
+
queryDenseVec = v;
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
catch { /* fallback to sparse */ }
|
|
1990
|
+
const results = this.memoryStore.searchContext(enrichedQuery, {
|
|
1991
|
+
limit: SEARCH_CONTEXT_LIMIT,
|
|
1992
|
+
recencyLimit: SEARCH_RECENCY_LIMIT,
|
|
1993
|
+
agentSlug,
|
|
1994
|
+
strict: strictIsolation,
|
|
1995
|
+
sessionKey: sessionKey ?? undefined,
|
|
1996
|
+
queryDenseVec,
|
|
1997
|
+
});
|
|
1967
1998
|
if (results?.length > 0) {
|
|
1968
1999
|
const accessedIds = results
|
|
1969
2000
|
.map((r) => r.chunkId)
|
|
@@ -2052,6 +2083,19 @@ You have a cost budget per message — not a hard turn limit. Work until the tas
|
|
|
2052
2083
|
return undefined;
|
|
2053
2084
|
})(),
|
|
2054
2085
|
]);
|
|
2086
|
+
// Render user model block (MemGPT-style core memory). Per-agent if
|
|
2087
|
+
// running as a hired agent, otherwise the global block. Empty string
|
|
2088
|
+
// when no slots are populated yet — context-assembler will skip the
|
|
2089
|
+
// slot rather than emit an empty heading.
|
|
2090
|
+
let userModelBlock = null;
|
|
2091
|
+
try {
|
|
2092
|
+
userModelBlock = this.memoryStore.renderUserModel?.(agentSlug ?? null) ?? null;
|
|
2093
|
+
if (!userModelBlock)
|
|
2094
|
+
userModelBlock = null;
|
|
2095
|
+
}
|
|
2096
|
+
catch {
|
|
2097
|
+
userModelBlock = null;
|
|
2098
|
+
}
|
|
2055
2099
|
// Assemble context within a priority-based budget
|
|
2056
2100
|
const assembled = await assembleContext({
|
|
2057
2101
|
totalBudget: SYSTEM_PROMPT_MAX_CONTEXT_CHARS,
|
|
@@ -2060,6 +2104,7 @@ You have a cost budget per message — not a hard turn limit. Work until the tas
|
|
|
2060
2104
|
memoryResults: results,
|
|
2061
2105
|
skillContext,
|
|
2062
2106
|
graphContext,
|
|
2107
|
+
userModelBlock,
|
|
2063
2108
|
isAutonomous: isAutonomous ?? false,
|
|
2064
2109
|
});
|
|
2065
2110
|
return assembled.text;
|