clementine-agent 1.18.149 → 1.18.150
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.
|
@@ -2054,13 +2054,29 @@ export class SelfImproveLoop {
|
|
|
2054
2054
|
}
|
|
2055
2055
|
}
|
|
2056
2056
|
catch { /* non-fatal */ }
|
|
2057
|
-
// Identify consistently failed approaches
|
|
2057
|
+
// Identify consistently failed approaches.
|
|
2058
|
+
// 1.18.150 — exact-string Set dedup let near-duplicate hypotheses ("improve
|
|
2059
|
+
// cron prompt clarity" vs "improve cron prompt for clarity") both make it
|
|
2060
|
+
// through and waste two of the five slots. Use the existing tokenize +
|
|
2061
|
+
// jaccard helpers (Set ≥0.85 collapse) to merge near-duplicates while
|
|
2062
|
+
// preserving genuinely distinct framings.
|
|
2058
2063
|
const failedHypotheses = history
|
|
2059
2064
|
.filter(e => !e.accepted && e.score < 0.3 && !e.type)
|
|
2060
2065
|
.map(e => e.hypothesis.slice(0, 80));
|
|
2061
2066
|
if (failedHypotheses.length > 0) {
|
|
2062
2067
|
lines.push('\n### Approaches That Scored Poorly (avoid these)');
|
|
2063
|
-
|
|
2068
|
+
const merged = [];
|
|
2069
|
+
const mergedTokens = [];
|
|
2070
|
+
for (const h of failedHypotheses) {
|
|
2071
|
+
const ht = tokenizeForDrift(h);
|
|
2072
|
+
if (mergedTokens.some(t => jaccardSimilarity(t, ht) >= 0.85))
|
|
2073
|
+
continue;
|
|
2074
|
+
merged.push(h);
|
|
2075
|
+
mergedTokens.push(ht);
|
|
2076
|
+
if (merged.length >= 5)
|
|
2077
|
+
break;
|
|
2078
|
+
}
|
|
2079
|
+
for (const h of merged) {
|
|
2064
2080
|
lines.push(`- "${h}"`);
|
|
2065
2081
|
}
|
|
2066
2082
|
}
|
|
@@ -325,7 +325,7 @@ export function registerAdminTools(server) {
|
|
|
325
325
|
const unique = [...new Set(tools)].sort();
|
|
326
326
|
writeFileSync(ALLOWED_TOOLS_EXTRA, JSON.stringify(unique, null, 2));
|
|
327
327
|
}
|
|
328
|
-
server.tool('allow_tool', 'Add a tool name to your self-managed allowedTools list. Use when
|
|
328
|
+
server.tool('allow_tool', 'Add a tool name to your self-managed allowedTools list (~/.clementine/allowed-tools-extra.json). Use when an SDK-inventory tool returns "not in function schema". Effective on your next query. Auto-refreshes the inventory probe if the tool isn\'t cached. Owner-DM only.', {
|
|
329
329
|
name: z.string().describe('Exact tool name (e.g. "mcp__claude_ai_Google_Drive__search_files")'),
|
|
330
330
|
reason: z.string().optional().describe('Brief note: why you need this tool. For audit trail.'),
|
|
331
331
|
}, async ({ name, reason }) => {
|
|
@@ -368,7 +368,7 @@ export function registerAdminTools(server) {
|
|
|
368
368
|
logger.info({ name: trimmed, reason, totalExtras: current.length }, 'allow_tool');
|
|
369
369
|
return textResult(`Added ${trimmed} to ~/.clementine/allowed-tools-extra.json (${current.length} total extras)${refreshNote}. Active on your next query — no daemon restart needed.${reason ? ` Reason: ${reason}` : ''}`);
|
|
370
370
|
});
|
|
371
|
-
server.tool('refresh_tool_inventory', 'Force a fresh probe of the SDK
|
|
371
|
+
server.tool('refresh_tool_inventory', 'Force a fresh probe of the SDK tool inventory to pick up newly added claude.ai connectors, Composio toolkits, or local MCP servers. Updates ~/.clementine/.tool-inventory.json + syncs claude-integrations.json and returns a diff. Owner-DM only.', {}, async () => {
|
|
372
372
|
const gate = requireOwnerDm();
|
|
373
373
|
if (!gate.ok)
|
|
374
374
|
return textResult(gate.message);
|
|
@@ -1025,7 +1025,7 @@ export function registerAdminTools(server) {
|
|
|
1025
1025
|
return textResult(lines.join('\n\n'));
|
|
1026
1026
|
});
|
|
1027
1027
|
// ── Add Cron Job ────────────────────────────────────────────────────────
|
|
1028
|
-
server.tool('add_cron_job', 'Add a new scheduled task.
|
|
1028
|
+
server.tool('add_cron_job', 'Add a new scheduled task. Propose the plan in chat and get user approval first. The `prompt` MUST be self-contained: name the actual recipients, template, and criteria — vague references ("recent leads", "this week\'s items") drift between chat-time and fire-time. Default `predictable: true` runs with only prompt + pinned skills/tools (no MEMORY.md, no auto-match). Set `predictable: false` only when the user explicitly wants dynamic re-resolution each fire.', {
|
|
1029
1029
|
name: z.string().describe('Job name (unique identifier)'),
|
|
1030
1030
|
schedule: z.string().describe('Cron expression (e.g., "0 9 * * 1" for Monday 9 AM)'),
|
|
1031
1031
|
prompt: z.string().describe('The prompt/instruction for the assistant to execute. SHOULD BE CONCRETE — list actual recipients, criteria, content. Vague prompts re-derive at fire-time and cause "agent agreed in chat but emailed wrong people" failures.'),
|
|
@@ -1143,7 +1143,7 @@ export function registerAdminTools(server) {
|
|
|
1143
1143
|
return textResult(`Added cron job "${jobName}":\n${details.join('\n')}\n\n${verifyMsg}${goalHint}`);
|
|
1144
1144
|
});
|
|
1145
1145
|
// ── Update Cron Job ─────────────────────────────────────────────────────
|
|
1146
|
-
server.tool('update_cron_job', 'Update an existing cron job in CRON.md. Partial — only fields you supply change.
|
|
1146
|
+
server.tool('update_cron_job', 'Update an existing cron job in CRON.md. Partial — only fields you supply change. Pass an empty array to clear a capability allowlist (skills/allowed_tools/allowed_mcp_servers/tags); empty string clears category. Daemon auto-reloads. Run preview_cron_job before relying on the change. Flipping `predictable` true→false makes the trick read MEMORY.md at fire-time — confirm the tradeoff with the user.', {
|
|
1147
1147
|
name: z.string().describe('Existing job name to update.'),
|
|
1148
1148
|
schedule: z.string().optional().describe('New cron expression.'),
|
|
1149
1149
|
prompt: z.string().optional().describe('New prompt.'),
|
|
@@ -1279,7 +1279,7 @@ export function registerAdminTools(server) {
|
|
|
1279
1279
|
return textResult(`Updated cron job "${jobName}":\n ${changed.join('\n ')}\n\nDaemon will pick up the new definition within ~2s. Use \`preview_cron_job\` to confirm what will actually run.`);
|
|
1280
1280
|
});
|
|
1281
1281
|
// ── Preview Cron Job ────────────────────────────────────────────────────
|
|
1282
|
-
server.tool('preview_cron_job', 'Show
|
|
1282
|
+
server.tool('preview_cron_job', 'Show what a cron job will send the agent on its next fire without dispatching. Composes the same context blocks the runner uses at fire time and returns the built prompt + resolved skills + effective tool/MCP allowlists + warnings. Use to sanity-check tricks after configuration.', {
|
|
1283
1283
|
name: z.string().describe('Exact name of the cron job to preview (use list_cron_jobs to see available).'),
|
|
1284
1284
|
}, async ({ name: jobName }) => {
|
|
1285
1285
|
const [{ parseCronJobs, parseAgentCronJobs }, { buildCronExecutionPlan }, { loadSkillByName }, { discoverMcpServers }] = await Promise.all([
|