clementine-agent 1.11.0 → 1.11.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.
package/dist/cli/dashboard.js
CHANGED
|
@@ -25849,9 +25849,10 @@ async function saveComposioApiKey() {
|
|
|
25849
25849
|
|
|
25850
25850
|
async function connectComposio(slug) {
|
|
25851
25851
|
try {
|
|
25852
|
-
|
|
25852
|
+
// Use apiFetch (not raw fetch) so the Authorization: Bearer header is
|
|
25853
|
+
// attached — the /api/* middleware rejects unauth'd POSTs with 401.
|
|
25854
|
+
var res = await apiFetch('/api/composio/toolkits/' + encodeURIComponent(slug) + '/authorize', {
|
|
25853
25855
|
method: 'POST',
|
|
25854
|
-
credentials: 'same-origin',
|
|
25855
25856
|
headers: { 'content-type': 'application/json' },
|
|
25856
25857
|
body: JSON.stringify({}),
|
|
25857
25858
|
});
|
|
@@ -25884,9 +25885,8 @@ async function connectComposio(slug) {
|
|
|
25884
25885
|
async function disconnectComposio(slug, connectionId) {
|
|
25885
25886
|
if (!confirm('Disconnect this ' + slug + ' account?')) return;
|
|
25886
25887
|
try {
|
|
25887
|
-
var res = await
|
|
25888
|
+
var res = await apiFetch('/api/composio/toolkits/' + encodeURIComponent(slug) + '/disconnect', {
|
|
25888
25889
|
method: 'POST',
|
|
25889
|
-
credentials: 'same-origin',
|
|
25890
25890
|
headers: { 'content-type': 'application/json' },
|
|
25891
25891
|
body: JSON.stringify({ connectionId: connectionId }),
|
|
25892
25892
|
});
|
|
@@ -98,11 +98,11 @@ export async function getPreferredUserId() {
|
|
|
98
98
|
// calls have to pass *some* user_id, and we want it to match whatever the
|
|
99
99
|
// user already has if possible. detectPreferredUserId() picks the user_id
|
|
100
100
|
// with the most existing connections, falling back to this constant.
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
const DEFAULT_NEW_CONNECTION_USER_ID = '';
|
|
101
|
+
// Used only when there are no existing connections to learn from. The real
|
|
102
|
+
// path is detectPreferredUserId() reading the user_id off existing records
|
|
103
|
+
// via the raw client — that's how we match Composio's web-UI auto-generated
|
|
104
|
+
// IDs like `pg-test-<uuid>`.
|
|
105
|
+
const DEFAULT_NEW_CONNECTION_USER_ID = 'default';
|
|
106
106
|
export function clementineUserId() {
|
|
107
107
|
return readComposioEnv('COMPOSIO_USER_ID') || DEFAULT_NEW_CONNECTION_USER_ID;
|
|
108
108
|
}
|
|
@@ -114,35 +114,41 @@ async function detectPreferredUserId(composio) {
|
|
|
114
114
|
return explicit;
|
|
115
115
|
if (detectedPreferredUserId !== null)
|
|
116
116
|
return detectedPreferredUserId;
|
|
117
|
-
// The
|
|
118
|
-
//
|
|
119
|
-
//
|
|
120
|
-
//
|
|
121
|
-
//
|
|
122
|
-
|
|
123
|
-
|
|
117
|
+
// The high-level wrapper's list() drops the snake_case `user_id` field
|
|
118
|
+
// during its camelCase transformation, so connections look like they have
|
|
119
|
+
// no user_id. Use the raw client (snake_case shape) to actually read the
|
|
120
|
+
// user_id Composio's web UI assigned (typically `pg-test-<uuid>` for
|
|
121
|
+
// dashboard-created connections). Without this, we'd default to "default"
|
|
122
|
+
// and composio.create() / toolkits.authorize() would never see existing
|
|
123
|
+
// connections — every tool call would 401.
|
|
124
124
|
try {
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
125
|
+
const rawClient = composio.client;
|
|
126
|
+
const resp = await rawClient.connectedAccounts.list({});
|
|
127
|
+
const items = (resp?.items ?? []);
|
|
128
|
+
const counts = new Map();
|
|
129
|
+
for (const it of items) {
|
|
130
|
+
// Prefer ACTIVE connections — expired ones often outnumber active ones
|
|
131
|
+
// (3 outlooks: 1 ACTIVE + 2 EXPIRED in real data).
|
|
132
|
+
if (it.status === 'ACTIVE' && typeof it.user_id === 'string' && it.user_id.length > 0) {
|
|
133
|
+
counts.set(it.user_id, (counts.get(it.user_id) ?? 0) + 2); // weight active higher
|
|
134
|
+
}
|
|
135
|
+
else if (typeof it.user_id === 'string' && it.user_id.length > 0) {
|
|
136
|
+
counts.set(it.user_id, (counts.get(it.user_id) ?? 0) + 1);
|
|
138
137
|
}
|
|
139
|
-
catch { /* try next */ }
|
|
140
138
|
}
|
|
139
|
+
if (counts.size > 0) {
|
|
140
|
+
const top = [...counts.entries()].sort((a, b) => b[1] - a[1])[0][0];
|
|
141
|
+
logger.info({ userId: top, candidates: counts.size }, 'Detected Composio user_id from existing connections');
|
|
142
|
+
detectedPreferredUserId = top;
|
|
143
|
+
return top;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
logger.warn({ err }, 'Raw client user_id probe failed — using fallback');
|
|
141
148
|
}
|
|
142
|
-
// No connections
|
|
143
|
-
// empty string,
|
|
144
|
-
//
|
|
145
|
-
// the user creates in Composio's dashboard.
|
|
149
|
+
// No existing connections. Fall back to "default" — composio.create()
|
|
150
|
+
// requires a non-empty string, and "default" is the conventional
|
|
151
|
+
// single-tenant value that Composio's quickstart uses.
|
|
146
152
|
detectedPreferredUserId = DEFAULT_NEW_CONNECTION_USER_ID;
|
|
147
153
|
return DEFAULT_NEW_CONNECTION_USER_ID;
|
|
148
154
|
}
|
|
@@ -48,29 +48,23 @@ export async function buildComposioMcpServers(slugs) {
|
|
|
48
48
|
}
|
|
49
49
|
return out;
|
|
50
50
|
}
|
|
51
|
-
async function buildOne(composio, slug,
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
//
|
|
55
|
-
|
|
56
|
-
//
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
const authConfig = (await composio.authConfigs.list({ toolkit: slug })).items[0];
|
|
51
|
+
async function buildOne(composio, slug, _connected) {
|
|
52
|
+
// composio.tools.get() returns the FLAT toolkit tools (OUTLOOK_LIST_MESSAGES,
|
|
53
|
+
// GMAIL_SEND_EMAIL, …) — exactly the namespacing the agent expects as
|
|
54
|
+
// mcp__outlook__OUTLOOK_LIST_MESSAGES. The alternative, composio.create()
|
|
55
|
+
// + session.tools(), uses Composio's tool-router pattern and only returns
|
|
56
|
+
// 5 meta-tools (COMPOSIO_SEARCH_TOOLS, COMPOSIO_MULTI_EXECUTE_TOOL, …),
|
|
57
|
+
// which doesn't match what the agent calls. Verified empirically:
|
|
58
|
+
// tools.get returns 50+ actual Outlook tools.
|
|
60
59
|
const userId = await getPreferredUserId();
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
...(activeCount >= 2
|
|
66
|
-
? { multiAccount: { enable: true, requireExplicitSelection: true } }
|
|
67
|
-
: {}),
|
|
68
|
-
});
|
|
69
|
-
const tools = await session.tools();
|
|
60
|
+
const toolsRaw = await composio.tools.get(userId, { toolkits: [slug], limit: 200 });
|
|
61
|
+
// tools.get can return an array OR an object depending on provider; normalise.
|
|
62
|
+
const toolsArr = Array.isArray(toolsRaw) ? toolsRaw : Object.values(toolsRaw);
|
|
63
|
+
const tools = toolsArr.filter((t) => t && typeof t.name === 'string' && typeof t.handler === 'function');
|
|
70
64
|
return createSdkMcpServer({
|
|
71
65
|
name: slug,
|
|
72
66
|
version: '0.1.0',
|
|
73
|
-
tools,
|
|
67
|
+
tools: tools,
|
|
74
68
|
});
|
|
75
69
|
}
|
|
76
70
|
//# sourceMappingURL=mcp-bridge.js.map
|