clementine-agent 1.9.0 → 1.9.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/dist/agent/assistant.js +29 -1
- package/dist/cli/dashboard.js +15 -2
- package/package.json +1 -1
package/dist/agent/assistant.js
CHANGED
|
@@ -379,13 +379,20 @@ const AUTO_MEMORY_PROMPT = `You are a memory extraction agent. Your ONLY job is
|
|
|
379
379
|
|
|
380
380
|
{current_memory}
|
|
381
381
|
|
|
382
|
+
## Current User Model (already known — DO NOT re-extract these)
|
|
383
|
+
|
|
384
|
+
{current_user_model}
|
|
385
|
+
|
|
382
386
|
## Where to save what (memory routing):
|
|
383
387
|
|
|
384
388
|
**Always-in-context core memory** (use the user_model tool — these stay top-of-mind in every future session):
|
|
385
389
|
- **Lasting facts about ${OWNER}** (role, location, identifiers, durable preferences, communication style) → user_model(action="append", slot="user_facts", content=...)
|
|
386
390
|
- **Active goals/intents** (what ${OWNER} is trying to accomplish right now) → user_model(action="append", slot="goals", content=...)
|
|
387
391
|
- **Key people/projects** (recurring relationships) → user_model(action="append", slot="relationships", content=...)
|
|
388
|
-
-
|
|
392
|
+
- **DEFAULT to action="append"** — it adds the new fact alongside what's already there.
|
|
393
|
+
- Only use action="replace" when CORRECTING an existing fact, and you MUST include the FULL slot content (everything from "Current User Model" above, with the correction applied). \`replace\` overwrites the entire slot — passing only the new fact wipes everything else.
|
|
394
|
+
- Never use action="clear" from this extractor. Clearing is a deliberate user action, not a memory-extraction outcome.
|
|
395
|
+
- Slots are capped at 2000 chars — older content rolls off on append automatically.
|
|
389
396
|
|
|
390
397
|
**Vault notes** (use memory_write/note_create — durable but retrieved on demand):
|
|
391
398
|
- **People mentioned** — names, relationships, context → create or update person notes in 02-People/
|
|
@@ -1638,6 +1645,7 @@ You have a cost budget per message — not a hard turn limit. Work until the tas
|
|
|
1638
1645
|
'Read', 'Write', 'Edit', 'Bash', 'Glob', 'Grep',
|
|
1639
1646
|
'WebSearch', 'WebFetch',
|
|
1640
1647
|
mcpTool('working_memory'),
|
|
1648
|
+
mcpTool('user_model'),
|
|
1641
1649
|
mcpTool('memory_read'),
|
|
1642
1650
|
mcpTool('memory_write'),
|
|
1643
1651
|
mcpTool('memory_search'),
|
|
@@ -3683,10 +3691,23 @@ You have a cost budget per message — not a hard turn limit. Work until the tas
|
|
|
3683
3691
|
// Non-fatal — proceed without corrections
|
|
3684
3692
|
}
|
|
3685
3693
|
}
|
|
3694
|
+
// Render current user_model state so the extractor can: (a) skip
|
|
3695
|
+
// re-extracting facts already there, (b) safely use action="replace"
|
|
3696
|
+
// by passing the full slot content with a correction applied. Scoped
|
|
3697
|
+
// to the active agent — Clementine sees global slots, hired agents
|
|
3698
|
+
// see their own per-agent slots.
|
|
3699
|
+
let currentUserModel = '(empty — no slots populated yet)';
|
|
3700
|
+
try {
|
|
3701
|
+
const rendered = this.memoryStore?.renderUserModel?.(profile?.slug ?? null);
|
|
3702
|
+
if (rendered && rendered.trim())
|
|
3703
|
+
currentUserModel = rendered;
|
|
3704
|
+
}
|
|
3705
|
+
catch { /* non-fatal */ }
|
|
3686
3706
|
const memPrompt = AUTO_MEMORY_PROMPT
|
|
3687
3707
|
.replace('{user_message}', userMessage)
|
|
3688
3708
|
.replace('{assistant_response}', truncatedResponse)
|
|
3689
3709
|
.replace('{current_memory}', currentMemory || '(empty — no existing memory yet)')
|
|
3710
|
+
.replace('{current_user_model}', currentUserModel)
|
|
3690
3711
|
.replace('{recent_corrections}', correctionsText);
|
|
3691
3712
|
const userMessageSnippet = userMessage.slice(0, 500);
|
|
3692
3713
|
const stream = query({
|
|
@@ -3706,6 +3727,13 @@ You have a cost budget per message — not a hard turn limit. Work until the tas
|
|
|
3706
3727
|
mcpTool('task_add'),
|
|
3707
3728
|
mcpTool('note_take'),
|
|
3708
3729
|
mcpTool('memory_read'),
|
|
3730
|
+
// Auto-extractor needs user_model to populate the always-in-context
|
|
3731
|
+
// core slots (user_facts, goals, relationships, agent_persona).
|
|
3732
|
+
// The MCP server boots with CLEMENTINE_TEAM_AGENT=<slug>, so writes
|
|
3733
|
+
// are scoped to the active agent automatically — Clementine's
|
|
3734
|
+
// sessions populate global slots, hired-agent sessions populate
|
|
3735
|
+
// that agent's per-agent slots.
|
|
3736
|
+
mcpTool('user_model'),
|
|
3709
3737
|
],
|
|
3710
3738
|
mcpServers: {
|
|
3711
3739
|
[TOOLS_SERVER]: {
|
package/dist/cli/dashboard.js
CHANGED
|
@@ -12698,8 +12698,8 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
12698
12698
|
|
|
12699
12699
|
<!-- User Model — MemGPT-style core memory blocks always loaded into context -->
|
|
12700
12700
|
<div class="tab-pane" id="tab-intelligence-user-model">
|
|
12701
|
-
<div style="color:var(--muted,#888);margin-bottom:12px;font-size:13px">
|
|
12702
|
-
|
|
12701
|
+
<div style="color:var(--muted,#888);margin-bottom:12px;font-size:13px;max-width:760px">
|
|
12702
|
+
<strong style="color:var(--text)">Always-in-context core memory.</strong> Four small slots (capped at 2000 chars each) that load into <em>every</em> conversation — distinct from MEMORY.md and the chunk store. The agent appends here automatically as you talk; you can also edit directly to correct or steer. Use the Scope dropdown to view per-agent slots (each hired agent maintains their own).
|
|
12703
12703
|
</div>
|
|
12704
12704
|
<div style="display:flex;gap:8px;margin-bottom:12px;align-items:center;flex-wrap:wrap">
|
|
12705
12705
|
<label style="font-size:13px;color:var(--text-secondary)">Scope:</label>
|
|
@@ -19160,7 +19160,20 @@ async function loadUserModel() {
|
|
|
19160
19160
|
relationships: 'People, projects, channels they regularly interact with.',
|
|
19161
19161
|
agent_persona: 'For multi-agent: this agent\\'s self-identity in its working relationship with the user.',
|
|
19162
19162
|
};
|
|
19163
|
+
// First-run hint: when every slot is empty, show a single explainer
|
|
19164
|
+
// banner above the (still editable) textareas so the user understands
|
|
19165
|
+
// both what this is and how to populate it. Suppressed once anything
|
|
19166
|
+
// is in place — at that point the metadata on each card is enough.
|
|
19167
|
+
var allEmpty = d.blocks.every(function(b) { return !(b.content || '').trim(); });
|
|
19163
19168
|
var html = '<div style="display:flex;flex-direction:column;gap:14px">';
|
|
19169
|
+
if (allEmpty) {
|
|
19170
|
+
html += '<div class="card" style="padding:14px;border-left:3px solid var(--accent,#f59e0b);background:var(--bg-input,#1a1a1a)">' +
|
|
19171
|
+
'<div style="font-weight:600;margin-bottom:6px">No core memory yet for this scope</div>' +
|
|
19172
|
+
'<div style="font-size:12px;color:var(--text-secondary);line-height:1.5">' +
|
|
19173
|
+
'These slots auto-populate as you chat — the agent extracts durable facts about you (your role, active goals, recurring people/projects) and appends them after each exchange. ' +
|
|
19174
|
+
'You can also seed from existing memory in one click, or type directly into any slot below and click Save.' +
|
|
19175
|
+
'</div></div>';
|
|
19176
|
+
}
|
|
19164
19177
|
for (var i = 0; i < d.blocks.length; i++) {
|
|
19165
19178
|
var b = d.blocks[i];
|
|
19166
19179
|
var label = labelMap[b.slot] || b.slot;
|