clementine-agent 1.13.1 → 1.13.2

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.
@@ -57,13 +57,15 @@ export interface ServiceAvailability {
57
57
  export declare function computeAvailability(composioConnectedSlugs: Set<string>, claudeDesktopActiveNames: Set<string>, preferences: Record<string, ToolSource>): ServiceAvailability[];
58
58
  /**
59
59
  * Build the system-prompt instruction listing which tool source the agent
60
- * should use for each service. Only includes services where:
61
- * - There IS a conflict (both sources connected), AND
62
- * - The user has explicitly picked a non-default preference, OR
63
- * - The user picked 'off' (so we tell the agent NOT to use it)
60
+ * should use for each service. Output ONLY for services with a real
61
+ * conflict (both sources connected). Includes the silent-default state
62
+ * too, so the agent knows the current rule without falling back to
63
+ * memory recall (which can hold stale preferences from past conversations).
64
64
  *
65
- * Returns empty string when no instruction is needed — that's the goal:
66
- * silent default, zero prompt overhead, until the user actually configures.
65
+ * Token shape:
66
+ * - 0 conflicts empty string (zero overhead)
67
+ * - N conflicts → ~70 char header + ~50 chars per conflict
68
+ * Compare to the previous always-on hardcoded block which was ~700 chars.
67
69
  */
68
70
  export declare function buildPromptInstruction(availability: ServiceAvailability[], preferences: Record<string, ToolSource>): string;
69
71
  //# sourceMappingURL=tool-preferences.d.ts.map
@@ -81,13 +81,15 @@ export function computeAvailability(composioConnectedSlugs, claudeDesktopActiveN
81
81
  }
82
82
  /**
83
83
  * Build the system-prompt instruction listing which tool source the agent
84
- * should use for each service. Only includes services where:
85
- * - There IS a conflict (both sources connected), AND
86
- * - The user has explicitly picked a non-default preference, OR
87
- * - The user picked 'off' (so we tell the agent NOT to use it)
84
+ * should use for each service. Output ONLY for services with a real
85
+ * conflict (both sources connected). Includes the silent-default state
86
+ * too, so the agent knows the current rule without falling back to
87
+ * memory recall (which can hold stale preferences from past conversations).
88
88
  *
89
- * Returns empty string when no instruction is needed — that's the goal:
90
- * silent default, zero prompt overhead, until the user actually configures.
89
+ * Token shape:
90
+ * - 0 conflicts empty string (zero overhead)
91
+ * - N conflicts → ~70 char header + ~50 chars per conflict
92
+ * Compare to the previous always-on hardcoded block which was ~700 chars.
91
93
  */
92
94
  export function buildPromptInstruction(availability, preferences) {
93
95
  const lines = [];
@@ -95,20 +97,23 @@ export function buildPromptInstruction(availability, preferences) {
95
97
  if (!a.hasConflict)
96
98
  continue;
97
99
  const userPref = preferences[a.service.id];
98
- if (!userPref)
99
- continue; // no explicit pref silent default, no prompt cost
100
- if (userPref === 'off') {
100
+ // Effective rule when no explicit preference: default to Composio.
101
+ // We surface this in the prompt anyway so the agent has a deterministic
102
+ // rule and doesn't recall a contradicting preference from memory.
103
+ const effective = userPref ?? 'composio';
104
+ if (effective === 'off') {
101
105
  lines.push(`- ${a.service.label}: do NOT use any of its tools (user disabled)`);
102
106
  }
103
- else if (userPref === 'composio' && a.service.composioSlug) {
104
- lines.push(`- ${a.service.label}: use \`mcp__${a.service.composioSlug}__*\` (NOT \`mcp__claude_ai_${a.service.claudeDesktopName}__*\`)`);
107
+ else if (effective === 'composio' && a.service.composioSlug) {
108
+ const note = userPref ? '' : ' [default]';
109
+ lines.push(`- ${a.service.label}: \`mcp__${a.service.composioSlug}__*\` (NOT \`mcp__claude_ai_${a.service.claudeDesktopName}__*\`)${note}`);
105
110
  }
106
- else if (userPref === 'claude-desktop' && a.service.claudeDesktopName) {
107
- lines.push(`- ${a.service.label}: use \`mcp__claude_ai_${a.service.claudeDesktopName}__*\` (NOT \`mcp__${a.service.composioSlug}__*\`)`);
111
+ else if (effective === 'claude-desktop' && a.service.claudeDesktopName) {
112
+ lines.push(`- ${a.service.label}: \`mcp__claude_ai_${a.service.claudeDesktopName}__*\` (NOT \`mcp__${a.service.composioSlug}__*\`)`);
108
113
  }
109
114
  }
110
115
  if (lines.length === 0)
111
116
  return '';
112
- return `## Tool Source Preferences\n\n${lines.join('\n')}`;
117
+ return `## Tool Source Preferences\n\nThese rules OVERRIDE any tool-source preference you may recall from memory. Do not consult memory for this — the canonical source is the dashboard's Tool Source Preferences (Settings → Integrations).\n\n${lines.join('\n')}`;
113
118
  }
114
119
  //# sourceMappingURL=tool-preferences.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clementine-agent",
3
- "version": "1.13.1",
3
+ "version": "1.13.2",
4
4
  "description": "Clementine — Personal AI Assistant (TypeScript)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",