clementine-agent 1.10.2 → 1.10.4
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/cli/dashboard.js
CHANGED
|
@@ -4387,16 +4387,21 @@ If the tool returns nothing or errors, return an empty array \`[]\`.`,
|
|
|
4387
4387
|
}
|
|
4388
4388
|
});
|
|
4389
4389
|
// ── Composio (1000+ third-party services via OAuth broker) ────
|
|
4390
|
-
app.get('/api/composio/status', (_req, res) => {
|
|
4391
|
-
|
|
4390
|
+
app.get('/api/composio/status', async (_req, res) => {
|
|
4391
|
+
// Use isComposioEnabled — checks both process.env (dashboard hot-reload)
|
|
4392
|
+
// and the .env file (survives daemon restart). Reading process.env
|
|
4393
|
+
// directly here was the bug: after restart, .env had the key but
|
|
4394
|
+
// process.env was empty, so the dashboard reported the key as unset.
|
|
4395
|
+
const c = await import('../integrations/composio/client.js');
|
|
4396
|
+
res.json({ enabled: c.isComposioEnabled() });
|
|
4392
4397
|
});
|
|
4393
4398
|
app.get('/api/composio/toolkits', async (_req, res) => {
|
|
4394
4399
|
try {
|
|
4395
|
-
|
|
4400
|
+
const c = await import('../integrations/composio/client.js');
|
|
4401
|
+
if (!c.isComposioEnabled()) {
|
|
4396
4402
|
res.json({ enabled: false, toolkits: [] });
|
|
4397
4403
|
return;
|
|
4398
4404
|
}
|
|
4399
|
-
const c = await import('../integrations/composio/client.js');
|
|
4400
4405
|
const [connected, configured, meta] = await Promise.all([
|
|
4401
4406
|
c.listConnectedToolkits(),
|
|
4402
4407
|
c.listToolkitSlugsWithAuthConfig(),
|
|
@@ -5217,11 +5222,16 @@ If the tool returns nothing or errors, return an empty array \`[]\`.`,
|
|
|
5217
5222
|
app.put('/api/settings/:key', async (req, res) => {
|
|
5218
5223
|
try {
|
|
5219
5224
|
const { key } = req.params;
|
|
5220
|
-
|
|
5225
|
+
let { value } = req.body;
|
|
5221
5226
|
if (typeof value !== 'string') {
|
|
5222
5227
|
res.status(400).json({ error: 'value must be a string' });
|
|
5223
5228
|
return;
|
|
5224
5229
|
}
|
|
5230
|
+
// Strip whitespace + invisible chars that commonly hitchhike when users
|
|
5231
|
+
// paste from a website. Without this, Composio's API rejects the key as
|
|
5232
|
+
// 401 even though the visible characters look right. Trim covers
|
|
5233
|
+
// newlines, tabs, regular spaces, and zero-width chars.
|
|
5234
|
+
value = value.trim().replace(/[-]/g, '');
|
|
5225
5235
|
// Allow known keys + any valid env var name (A-Z, 0-9, _)
|
|
5226
5236
|
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {
|
|
5227
5237
|
res.status(400).json({ error: `Invalid key format: ${key}` });
|
|
@@ -395,9 +395,17 @@ export async function authorizeToolkit(slug, opts) {
|
|
|
395
395
|
// 1. Find or create an auth config. session.authorize() doesn't auto-create
|
|
396
396
|
// so we have to pass authConfigId explicitly to connectedAccounts.initiate.
|
|
397
397
|
let authConfigId;
|
|
398
|
-
|
|
398
|
+
let existingConfig;
|
|
399
|
+
try {
|
|
400
|
+
existingConfig = (await composio.authConfigs.list({ toolkit: slug })).items[0];
|
|
401
|
+
}
|
|
402
|
+
catch (err) {
|
|
403
|
+
logger.error({ err, slug, step: 'authConfigs.list' }, 'Composio authorize failed');
|
|
404
|
+
throw err;
|
|
405
|
+
}
|
|
399
406
|
if (existingConfig) {
|
|
400
407
|
authConfigId = existingConfig.id;
|
|
408
|
+
logger.debug({ slug, authConfigId }, 'Reusing existing auth config');
|
|
401
409
|
}
|
|
402
410
|
else {
|
|
403
411
|
try {
|
|
@@ -406,12 +414,17 @@ export async function authorizeToolkit(slug, opts) {
|
|
|
406
414
|
name: `${displayNameFor(slug)} Auth Config`,
|
|
407
415
|
});
|
|
408
416
|
authConfigId = created.id;
|
|
417
|
+
logger.debug({ slug, authConfigId }, 'Created managed auth config');
|
|
409
418
|
}
|
|
410
419
|
catch (err) {
|
|
411
|
-
// 400 → Composio doesn't host a managed OAuth app for this toolkit;
|
|
412
|
-
// user must register their own via the Composio dashboard.
|
|
413
420
|
const status = err?.status;
|
|
414
|
-
|
|
421
|
+
logger.warn({ err, slug, status, step: 'authConfigs.create' }, 'authConfigs.create rejected — likely needs BYO setup');
|
|
422
|
+
// 400 → Composio doesn't host a managed OAuth app for this toolkit.
|
|
423
|
+
// 401/403 → key lacks permission to create managed auth configs (common
|
|
424
|
+
// for Google services where Composio's plan tier requires you to
|
|
425
|
+
// register your own Google OAuth project). Either way, the user fix
|
|
426
|
+
// is the same: set it up once in Composio's auth-configs dashboard.
|
|
427
|
+
if (status === 400 || status === 401 || status === 403) {
|
|
415
428
|
throw new ComposioNeedsAuthConfigError(slug, String(err));
|
|
416
429
|
}
|
|
417
430
|
throw err;
|
|
@@ -424,12 +437,19 @@ export async function authorizeToolkit(slug, opts) {
|
|
|
424
437
|
// freshly authorized Gmail lands next to the existing Outlook (etc.) under
|
|
425
438
|
// the same user_id. Falls back to env override or "default".
|
|
426
439
|
const userId = await detectPreferredUserId(composio);
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
440
|
+
try {
|
|
441
|
+
const conn = await composio.connectedAccounts.initiate(userId, authConfigId, {
|
|
442
|
+
...(existing.length > 0 ? { allowMultiple: true } : {}),
|
|
443
|
+
...(opts?.callbackUrl ? { callbackUrl: opts.callbackUrl } : {}),
|
|
444
|
+
...(opts?.alias ? { alias: opts.alias } : {}),
|
|
445
|
+
});
|
|
446
|
+
logger.debug({ slug, userId, connectionId: conn.id }, 'Initiated connection');
|
|
447
|
+
return { redirectUrl: conn.redirectUrl ?? null, connectionId: conn.id };
|
|
448
|
+
}
|
|
449
|
+
catch (err) {
|
|
450
|
+
logger.error({ err, slug, userId, authConfigId, step: 'connectedAccounts.initiate' }, 'Composio initiate failed');
|
|
451
|
+
throw err;
|
|
452
|
+
}
|
|
433
453
|
}
|
|
434
454
|
export async function disconnectToolkit(connectionId) {
|
|
435
455
|
const composio = getComposio();
|