clementine-agent 1.12.2 → 1.12.3

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.
@@ -4555,6 +4555,21 @@ If the tool returns nothing or errors, return an empty array \`[]\`.`,
4555
4555
  res.status(500).json({ error: String(err) });
4556
4556
  }
4557
4557
  });
4558
+ // Force-refresh the Composio caches. Useful when the user just made a
4559
+ // connection in Composio's web UI and wants the agent to pick it up
4560
+ // immediately instead of waiting up to 60s for the user_id cache to
4561
+ // expire. Agents can also call this after surfacing a "needs OAuth"
4562
+ // error to retry cleanly.
4563
+ app.post('/api/composio/refresh', async (_req, res) => {
4564
+ try {
4565
+ const c = await import('../integrations/composio/client.js');
4566
+ c.resetComposioClient();
4567
+ res.json({ ok: true, message: 'Composio caches cleared — next query will re-detect.' });
4568
+ }
4569
+ catch (err) {
4570
+ res.status(500).json({ error: String(err) });
4571
+ }
4572
+ });
4558
4573
  // ── CRON CRUD routes ──────────────────────────────────────────
4559
4574
  app.get('/api/projects', (_req, res) => {
4560
4575
  try {
@@ -108,13 +108,22 @@ export function clementineUserId() {
108
108
  return readComposioEnv('COMPOSIO_USER_ID') || DEFAULT_NEW_CONNECTION_USER_ID;
109
109
  }
110
110
  // Cached after first detection — avoids extra API calls per authorize.
111
+ // Cache the detected user_id but only briefly. New connections made via
112
+ // Composio's web UI (outside Clementine) need to be picked up without a
113
+ // daemon restart — long-lived caching breaks that. 60s is short enough
114
+ // for "hit dashboard → connect in Composio web → use it from agent" to
115
+ // work without explicit invalidation, and long enough that within-burst
116
+ // queries don't hammer the API.
111
117
  let detectedPreferredUserId = null;
118
+ let detectedAt = 0;
119
+ const USER_ID_CACHE_TTL_MS = 60_000;
112
120
  async function detectPreferredUserId(composio) {
113
121
  const explicit = readComposioEnv('COMPOSIO_USER_ID');
114
122
  if (explicit)
115
123
  return explicit;
116
- if (detectedPreferredUserId !== null)
124
+ if (detectedPreferredUserId !== null && Date.now() - detectedAt < USER_ID_CACHE_TTL_MS) {
117
125
  return detectedPreferredUserId;
126
+ }
118
127
  // The high-level wrapper's list() drops the snake_case `user_id` field
119
128
  // during its camelCase transformation, so connections look like they have
120
129
  // no user_id. Use the raw client (snake_case shape) to actually read the
@@ -141,6 +150,7 @@ async function detectPreferredUserId(composio) {
141
150
  const top = [...counts.entries()].sort((a, b) => b[1] - a[1])[0][0];
142
151
  logger.info({ userId: top, candidates: counts.size }, 'Detected Composio user_id from existing connections');
143
152
  detectedPreferredUserId = top;
153
+ detectedAt = Date.now();
144
154
  return top;
145
155
  }
146
156
  }
@@ -151,6 +161,7 @@ async function detectPreferredUserId(composio) {
151
161
  // requires a non-empty string, and "default" is the conventional
152
162
  // single-tenant value that Composio's quickstart uses.
153
163
  detectedPreferredUserId = DEFAULT_NEW_CONNECTION_USER_ID;
164
+ detectedAt = Date.now();
154
165
  return DEFAULT_NEW_CONNECTION_USER_ID;
155
166
  }
156
167
  export function displayNameFor(slug) {
@@ -517,6 +528,10 @@ _opts) {
517
528
  try {
518
529
  const conn = await composio.toolkits.authorize(userId, slug);
519
530
  logger.info({ slug, userId, connectionId: conn.id }, 'Composio authorize OK');
531
+ // Force re-detect on the next query so the new connection (and any
532
+ // others created in parallel via Composio's web UI) get picked up
533
+ // immediately, even within the 60s TTL window.
534
+ detectedPreferredUserId = null;
520
535
  return { redirectUrl: conn.redirectUrl ?? null, connectionId: conn.id };
521
536
  }
522
537
  catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clementine-agent",
3
- "version": "1.12.2",
3
+ "version": "1.12.3",
4
4
  "description": "Clementine — Personal AI Assistant (TypeScript)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",