@koda-sl/baker-bridge 0.116.0 → 0.117.0-dev.933ebc23d

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.
@@ -14,7 +14,7 @@ export declare const CONNECTION_INPUT_TOOL_NAME = "mcp__baker_ui__request_connec
14
14
  */
15
15
  export declare const CONNECTION_PLATFORMS: readonly ["google-ads", "linkedin", "meta", "google-analytics", "google-search-console", "google-tag-manager", "x-ads", "hubspot", "google-drive", "highlevel", "pipedrive", "calendly", "savvycal"];
16
16
  export type ConnectionPlatform = (typeof CONNECTION_PLATFORMS)[number];
17
- declare const connectionRequestShape: z.ZodObject<{
17
+ declare const connectionRequestShape: z.ZodUnion<readonly [z.ZodObject<{
18
18
  platform: z.ZodEnum<{
19
19
  calendly: "calendly";
20
20
  "google-ads": "google-ads";
@@ -32,9 +32,30 @@ declare const connectionRequestShape: z.ZodObject<{
32
32
  }>;
33
33
  reason: z.ZodString;
34
34
  choose: z.ZodOptional<z.ZodLiteral<"media-folder">>;
35
- }, z.core.$strip>;
35
+ }, z.core.$strip>, z.ZodObject<{
36
+ app: z.ZodString;
37
+ reason: z.ZodString;
38
+ }, z.core.$strip>, z.ZodObject<{
39
+ server: z.ZodObject<{
40
+ name: z.ZodString;
41
+ url: z.ZodString;
42
+ auth: z.ZodOptional<z.ZodEnum<{
43
+ key: "key";
44
+ none: "none";
45
+ "sign-in": "sign-in";
46
+ }>>;
47
+ keyHeader: z.ZodOptional<z.ZodString>;
48
+ scope: z.ZodOptional<z.ZodEnum<{
49
+ company: "company";
50
+ org: "org";
51
+ user: "user";
52
+ user_org: "user_org";
53
+ }>>;
54
+ }, z.core.$strip>;
55
+ reason: z.ZodString;
56
+ }, z.core.$strip>]>;
36
57
  export declare const connectionInputToolShape: {
37
- connections: z.ZodArray<z.ZodObject<{
58
+ connections: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
38
59
  platform: z.ZodEnum<{
39
60
  calendly: "calendly";
40
61
  "google-ads": "google-ads";
@@ -52,10 +73,31 @@ export declare const connectionInputToolShape: {
52
73
  }>;
53
74
  reason: z.ZodString;
54
75
  choose: z.ZodOptional<z.ZodLiteral<"media-folder">>;
55
- }, z.core.$strip>>;
76
+ }, z.core.$strip>, z.ZodObject<{
77
+ app: z.ZodString;
78
+ reason: z.ZodString;
79
+ }, z.core.$strip>, z.ZodObject<{
80
+ server: z.ZodObject<{
81
+ name: z.ZodString;
82
+ url: z.ZodString;
83
+ auth: z.ZodOptional<z.ZodEnum<{
84
+ key: "key";
85
+ none: "none";
86
+ "sign-in": "sign-in";
87
+ }>>;
88
+ keyHeader: z.ZodOptional<z.ZodString>;
89
+ scope: z.ZodOptional<z.ZodEnum<{
90
+ company: "company";
91
+ org: "org";
92
+ user: "user";
93
+ user_org: "user_org";
94
+ }>>;
95
+ }, z.core.$strip>;
96
+ reason: z.ZodString;
97
+ }, z.core.$strip>]>>;
56
98
  resolution: z.ZodOptional<z.ZodObject<{}, z.core.$catchall<z.ZodUnknown>>>;
57
99
  };
58
- export declare const connectionInputResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
100
+ export declare const connectionInputResultSchema: z.ZodUnion<readonly [z.ZodObject<{
59
101
  status: z.ZodLiteral<"connected">;
60
102
  platform: z.ZodEnum<{
61
103
  calendly: "calendly";
@@ -94,10 +136,39 @@ export declare const connectionInputResultSchema: z.ZodDiscriminatedUnion<[z.Zod
94
136
  "x-ads": "x-ads";
95
137
  }>;
96
138
  reason: z.ZodOptional<z.ZodString>;
97
- }, z.core.$strip>], "status">;
139
+ }, z.core.$strip>, z.ZodObject<{
140
+ status: z.ZodLiteral<"connected">;
141
+ app: z.ZodString;
142
+ scope: z.ZodEnum<{
143
+ company: "company";
144
+ org: "org";
145
+ user: "user";
146
+ user_org: "user_org";
147
+ }>;
148
+ accountLabel: z.ZodOptional<z.ZodString>;
149
+ readOnly: z.ZodOptional<z.ZodBoolean>;
150
+ }, z.core.$strip>, z.ZodObject<{
151
+ status: z.ZodLiteral<"declined">;
152
+ app: z.ZodString;
153
+ reason: z.ZodOptional<z.ZodString>;
154
+ }, z.core.$strip>, z.ZodObject<{
155
+ status: z.ZodLiteral<"connected">;
156
+ server: z.ZodString;
157
+ scope: z.ZodEnum<{
158
+ company: "company";
159
+ org: "org";
160
+ user: "user";
161
+ user_org: "user_org";
162
+ }>;
163
+ problem: z.ZodOptional<z.ZodString>;
164
+ }, z.core.$strip>, z.ZodObject<{
165
+ status: z.ZodLiteral<"declined">;
166
+ server: z.ZodString;
167
+ reason: z.ZodOptional<z.ZodString>;
168
+ }, z.core.$strip>]>;
98
169
  export type ConnectionInputResult = z.infer<typeof connectionInputResultSchema>;
99
170
  export declare const connectionInputResolutionSchema: z.ZodObject<{
100
- results: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
171
+ results: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
101
172
  status: z.ZodLiteral<"connected">;
102
173
  platform: z.ZodEnum<{
103
174
  calendly: "calendly";
@@ -136,9 +207,45 @@ export declare const connectionInputResolutionSchema: z.ZodObject<{
136
207
  "x-ads": "x-ads";
137
208
  }>;
138
209
  reason: z.ZodOptional<z.ZodString>;
139
- }, z.core.$strip>], "status">>;
210
+ }, z.core.$strip>, z.ZodObject<{
211
+ status: z.ZodLiteral<"connected">;
212
+ app: z.ZodString;
213
+ scope: z.ZodEnum<{
214
+ company: "company";
215
+ org: "org";
216
+ user: "user";
217
+ user_org: "user_org";
218
+ }>;
219
+ accountLabel: z.ZodOptional<z.ZodString>;
220
+ readOnly: z.ZodOptional<z.ZodBoolean>;
221
+ }, z.core.$strip>, z.ZodObject<{
222
+ status: z.ZodLiteral<"declined">;
223
+ app: z.ZodString;
224
+ reason: z.ZodOptional<z.ZodString>;
225
+ }, z.core.$strip>, z.ZodObject<{
226
+ status: z.ZodLiteral<"connected">;
227
+ server: z.ZodString;
228
+ scope: z.ZodEnum<{
229
+ company: "company";
230
+ org: "org";
231
+ user: "user";
232
+ user_org: "user_org";
233
+ }>;
234
+ problem: z.ZodOptional<z.ZodString>;
235
+ }, z.core.$strip>, z.ZodObject<{
236
+ status: z.ZodLiteral<"declined">;
237
+ server: z.ZodString;
238
+ reason: z.ZodOptional<z.ZodString>;
239
+ }, z.core.$strip>]>>;
140
240
  }, z.core.$strip>;
141
241
  export type ConnectionInputResolution = z.infer<typeof connectionInputResolutionSchema>;
242
+ /**
243
+ * Whether the user connected something that brings MCP tools — an app or a
244
+ * server. Only then is the turn's server set reloaded: a platform is read with
245
+ * `baker` commands and adds no tool, and reloading for nothing would rewrite
246
+ * the tool list, and the prompt cache with it.
247
+ */
248
+ export declare function toolsConnected(resolution: ConnectionInputResolution): boolean;
142
249
  /** Parse-at-boundary for the resolution posted to `POST /connection-input-decision`. */
143
250
  export declare function parseConnectionInputResolution(value: unknown): ConnectionInputResolution | null;
144
251
  export type ConnectionInputRequest = z.infer<typeof connectionRequestShape>;
@@ -146,11 +253,12 @@ export type ConnectionInputRequest = z.infer<typeof connectionRequestShape>;
146
253
  * `canUseTool` sees the RAW model input — MCP validation hasn't run yet — so the
147
254
  * requests are normalized here before anything downstream trusts them. Unknown
148
255
  * platforms (TikTok Ads, a hallucinated id) are dropped rather than shown as a
149
- * dead tab.
256
+ * dead tab. The dashboard applies the same rules (`connectionRequestsFromToolInput`)
257
+ * because it resolves tabs by index into this list.
150
258
  */
151
259
  export declare function normalizeConnectionInputToolInput(input: unknown): ConnectionInputRequest[];
152
260
  export declare function createConnectionInputTool(): import("@anthropic-ai/claude-agent-sdk").SdkMcpToolDefinition<{
153
- connections: z.ZodArray<z.ZodObject<{
261
+ connections: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
154
262
  platform: z.ZodEnum<{
155
263
  calendly: "calendly";
156
264
  "google-ads": "google-ads";
@@ -168,7 +276,28 @@ export declare function createConnectionInputTool(): import("@anthropic-ai/claud
168
276
  }>;
169
277
  reason: z.ZodString;
170
278
  choose: z.ZodOptional<z.ZodLiteral<"media-folder">>;
171
- }, z.core.$strip>>;
279
+ }, z.core.$strip>, z.ZodObject<{
280
+ app: z.ZodString;
281
+ reason: z.ZodString;
282
+ }, z.core.$strip>, z.ZodObject<{
283
+ server: z.ZodObject<{
284
+ name: z.ZodString;
285
+ url: z.ZodString;
286
+ auth: z.ZodOptional<z.ZodEnum<{
287
+ key: "key";
288
+ none: "none";
289
+ "sign-in": "sign-in";
290
+ }>>;
291
+ keyHeader: z.ZodOptional<z.ZodString>;
292
+ scope: z.ZodOptional<z.ZodEnum<{
293
+ company: "company";
294
+ org: "org";
295
+ user: "user";
296
+ user_org: "user_org";
297
+ }>>;
298
+ }, z.core.$strip>;
299
+ reason: z.ZodString;
300
+ }, z.core.$strip>]>>;
172
301
  resolution: z.ZodOptional<z.ZodObject<{}, z.core.$catchall<z.ZodUnknown>>>;
173
302
  }>;
174
303
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"connection-input.d.ts","sourceRoot":"","sources":["../../src/hono/connection-input.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,0BAA0B,sCAAsC,CAAC;AAE9E;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,YAC/B,YAAY,EACZ,UAAU,EACV,MAAM,EACN,kBAAkB,EAClB,uBAAuB,EACvB,oBAAoB,EACpB,OAAO,EACP,SAAS,EACT,cAAc,EACd,WAAW,EACX,WAAW,EACX,UAAU,EACV,UAAU,CACF,CAAC;AAEX,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvE,QAAA,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;iBAW1B,CAAC;AAEH,eAAO,MAAM,wBAAwB;IACnC,WAAW;;;;;;;;;;;;;;;;;;;IAKX,UAAU;CAKX,CAAC;AAIF,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6BAkBtC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAA8D,CAAC;AAC3G,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AAExF,wFAAwF;AACxF,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,OAAO,GAAG,yBAAyB,GAAG,IAAI,CAG/F;AAED,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAE5E;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB,EAAE,CAmB1F;AAUD,wBAAgB,yBAAyB;;;;;;;;;;;;;;;;;;;;;GAUxC"}
1
+ {"version":3,"file":"connection-input.d.ts","sourceRoot":"","sources":["../../src/hono/connection-input.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,0BAA0B,sCAAsC,CAAC;AAE9E;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,YAC/B,YAAY,EACZ,UAAU,EACV,MAAM,EACN,kBAAkB,EAClB,uBAAuB,EACvB,oBAAoB,EACpB,OAAO,EACP,SAAS,EACT,cAAc,EACd,WAAW,EACX,WAAW,EACX,UAAU,EACV,UAAU,CACF,CAAC;AAEX,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AA8DvE,QAAA,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBAAuE,CAAC;AAEpG,eAAO,MAAM,wBAAwB;IACnC,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAKX,UAAU;CAKX,CAAC;AAIF,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBAkCtC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAA8D,CAAC;AAC3G,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AAExF;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,yBAAyB,GAAG,OAAO,CAE7E;AAED,wFAAwF;AACxF,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,OAAO,GAAG,yBAAyB,GAAG,IAAI,CAG/F;AAED,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAwB5E;;;;;;GAMG;AACH,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB,EAAE,CAoB1F;AAcD,wBAAgB,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAUxC"}
@@ -6,6 +6,11 @@
6
6
  * Console, Tag Manager), where they also pick which accounts it may read, or a
7
7
  * tool (HubSpot, Google Drive, GoHighLevel, Pipedrive, Calendly, SavvyCal),
8
8
  * where connecting is the whole answer — without the user leaving the chat.
9
+ * It also adds tools: a remote MCP server the user described (`{ server }`,
10
+ * filled in from their instructions) or, when the vendor has none, a managed
11
+ * app from the catalog (`{ app }`). Those load into the running query once the
12
+ * card resolves (`BridgeJobExecutor.reloadMcpServers`), so the agent can call
13
+ * them in the same turn.
9
14
  *
10
15
  * Nothing confidential passes through the model: the bridge parks the turn in
11
16
  * `canUseTool`, the dashboard runs the OAuth popup and writes the selection onto
@@ -47,7 +52,7 @@ export const CONNECTION_PLATFORMS = [
47
52
  "calendly",
48
53
  "savvycal",
49
54
  ];
50
- const connectionRequestShape = z.object({
55
+ const platformRequestShape = z.object({
51
56
  platform: z.enum(CONNECTION_PLATFORMS).describe("Which platform the user needs to connect"),
52
57
  reason: z
53
58
  .string()
@@ -57,12 +62,50 @@ const connectionRequestShape = z.object({
57
62
  .optional()
58
63
  .describe("Google Drive only: the user picks a folder whose images and videos Baker imports into the libraries (a media source). Set it whenever the user wants a Drive folder's photos or videos in Baker."),
59
64
  });
65
+ /** Who reaches a connected app or server — mirrors the custom-MCP scope model. */
66
+ const REACH = ["user", "user_org", "company", "org"];
67
+ const serverShape = z.object({
68
+ name: z
69
+ .string()
70
+ .min(1)
71
+ .describe("Short lowercase slug for the server, e.g. `acme` — its tools become mcp__<name>__*"),
72
+ url: z.string().min(1).describe("The FULL https endpoint, usually ending in /mcp — never just the domain"),
73
+ auth: z
74
+ .enum(["none", "key", "sign-in"])
75
+ .optional()
76
+ .describe("How it signs in, from the vendor's instructions: `none` (public), `key` (an API key sent in a header — the user types it into the card, never into the chat), `sign-in` (the server runs its own sign-in popup). Omit when unsure: the card tries a sign-in and falls back to nothing."),
77
+ keyHeader: z
78
+ .string()
79
+ .min(1)
80
+ .optional()
81
+ .describe("`key` only: the header the key goes in, e.g. `Authorization` or `X-API-Key`"),
82
+ scope: z
83
+ .enum(REACH)
84
+ .optional()
85
+ .describe("Who reaches it: `company` (everyone in this company — the default), `user` (only the person asking, here), `user_org` (only them, in every company of the organization), `org` (everyone in every company — admins only). The user can change it in the card."),
86
+ });
87
+ const appRequestShape = z.object({
88
+ app: z
89
+ .string()
90
+ .min(1)
91
+ .describe("A managed app's slug from `baker mcp catalog --search <name>` — the fallback when the vendor has no MCP server"),
92
+ reason: z
93
+ .string()
94
+ .describe("One short sentence, in the user's terms, saying what you'll be able to do once it's connected"),
95
+ });
96
+ const serverRequestShape = z.object({
97
+ server: serverShape,
98
+ reason: z
99
+ .string()
100
+ .describe("One short sentence, in the user's terms, saying what you'll be able to do once it's connected"),
101
+ });
102
+ const connectionRequestShape = z.union([platformRequestShape, appRequestShape, serverRequestShape]);
60
103
  export const connectionInputToolShape = {
61
104
  connections: z
62
105
  .array(connectionRequestShape)
63
106
  .min(1)
64
107
  .max(5)
65
- .describe("Platforms to ask for; each becomes a tab the user resolves in one form"),
108
+ .describe("Platforms, apps and servers to ask for; each becomes a tab the user resolves in one form"),
66
109
  resolution: z
67
110
  .object({})
68
111
  .catchall(z.unknown())
@@ -70,7 +113,7 @@ export const connectionInputToolShape = {
70
113
  .describe("Internal — injected by the bridge after the user resolves the form. Never set this yourself."),
71
114
  };
72
115
  // --- Redacted resolution echoed back to the model ---
73
- export const connectionInputResultSchema = z.discriminatedUnion("status", [
116
+ export const connectionInputResultSchema = z.union([
74
117
  z.object({
75
118
  status: z.literal("connected"),
76
119
  platform: z.enum(CONNECTION_PLATFORMS),
@@ -88,18 +131,67 @@ export const connectionInputResultSchema = z.discriminatedUnion("status", [
88
131
  platform: z.enum(CONNECTION_PLATFORMS),
89
132
  reason: z.string().optional(),
90
133
  }),
134
+ z.object({
135
+ status: z.literal("connected"),
136
+ app: z.string(),
137
+ scope: z.enum(REACH),
138
+ accountLabel: z.string().optional(),
139
+ readOnly: z.boolean().optional(),
140
+ }),
141
+ z.object({ status: z.literal("declined"), app: z.string(), reason: z.string().optional() }),
142
+ z.object({
143
+ status: z.literal("connected"),
144
+ server: z.string(),
145
+ scope: z.enum(REACH),
146
+ /** What a person has to fix before its tools answer — the address, the sign-in or the key. */
147
+ problem: z.string().optional(),
148
+ }),
149
+ z.object({ status: z.literal("declined"), server: z.string(), reason: z.string().optional() }),
91
150
  ]);
92
151
  export const connectionInputResolutionSchema = z.object({ results: z.array(connectionInputResultSchema) });
152
+ /**
153
+ * Whether the user connected something that brings MCP tools — an app or a
154
+ * server. Only then is the turn's server set reloaded: a platform is read with
155
+ * `baker` commands and adds no tool, and reloading for nothing would rewrite
156
+ * the tool list, and the prompt cache with it.
157
+ */
158
+ export function toolsConnected(resolution) {
159
+ return resolution.results.some((result) => result.status === "connected" && ("app" in result || "server" in result));
160
+ }
93
161
  /** Parse-at-boundary for the resolution posted to `POST /connection-input-decision`. */
94
162
  export function parseConnectionInputResolution(value) {
95
163
  const parsed = connectionInputResolutionSchema.safeParse(value);
96
164
  return parsed.success ? parsed.data : null;
97
165
  }
166
+ /** The tab's identity, for collapsing the same ask made twice. */
167
+ function requestKey(request) {
168
+ if ("app" in request)
169
+ return `app:${request.app}`;
170
+ if ("server" in request)
171
+ return `server:${request.server.name}`;
172
+ return `platform:${request.platform}`;
173
+ }
174
+ /** Drop what a request's own kind does not use, so the card never asks for it. */
175
+ function trimRequest(request) {
176
+ if ("server" in request) {
177
+ const { keyHeader, ...server } = request.server;
178
+ // A key header only means something on a server that signs in with a key.
179
+ const keepHeader = keyHeader && (server.auth === undefined || server.auth === "key");
180
+ return { ...request, server: keepHeader ? { ...server, keyHeader } : server };
181
+ }
182
+ if ("app" in request)
183
+ return request;
184
+ // Choosing a folder is a Google Drive thing; on any other platform it would
185
+ // ask the dashboard for a picker that does not exist.
186
+ const { choose, ...platform } = request;
187
+ return choose && platform.platform === "google-drive" ? { ...platform, choose } : platform;
188
+ }
98
189
  /**
99
190
  * `canUseTool` sees the RAW model input — MCP validation hasn't run yet — so the
100
191
  * requests are normalized here before anything downstream trusts them. Unknown
101
192
  * platforms (TikTok Ads, a hallucinated id) are dropped rather than shown as a
102
- * dead tab.
193
+ * dead tab. The dashboard applies the same rules (`connectionRequestsFromToolInput`)
194
+ * because it resolves tabs by index into this list.
103
195
  */
104
196
  export function normalizeConnectionInputToolInput(input) {
105
197
  if (typeof input !== "object" || input === null) {
@@ -110,22 +202,27 @@ export function normalizeConnectionInputToolInput(input) {
110
202
  const requests = [];
111
203
  for (const entry of raw) {
112
204
  const parsed = connectionRequestShape.safeParse(entry);
113
- if (!parsed.success || seen.has(parsed.data.platform)) {
205
+ if (!parsed.success) {
206
+ continue;
207
+ }
208
+ const key = requestKey(parsed.data);
209
+ if (seen.has(key)) {
114
210
  continue;
115
211
  }
116
- seen.add(parsed.data.platform);
117
- // Choosing a folder is a Google Drive thing; on any other platform it would
118
- // ask the dashboard for a picker that does not exist.
119
- const { choose, ...request } = parsed.data;
120
- requests.push(choose && request.platform === "google-drive" ? { ...request, choose } : request);
212
+ seen.add(key);
213
+ requests.push(trimRequest(parsed.data));
121
214
  }
122
215
  return requests;
123
216
  }
124
217
  const CONNECTION_INPUT_TOOL_DESCRIPTION = [
125
- "Ask the user to connect — or reconnect — one of Baker's connections, inside the chat: an ad or data platform (Google Ads, LinkedIn Ads, Meta Ads, X Ads, Google Analytics 4, Google Search Console, Google Tag Manager), where they also pick which accounts Baker may read, or a tool (HubSpot, Google Drive, GoHighLevel, Pipedrive, Calendly, SavvyCal). BLOCKS until they resolve it in the dashboard.",
126
- "Use it the moment a command tells you a platform isn't connected, OR that it is connected but does not allow what you asked (a `request_connection` fix, `HUBSPOT_RECONNECT_REQUIRED`, a read-only connection) — the card shows Reconnect when the connection exists. Never tell the user to go to Settings instead. Each entry in `connections` becomes a tab, so ask for everything the task needs in ONE call.",
218
+ "Ask the user to connect — or reconnect — something inside the chat. BLOCKS until they resolve it in the dashboard. Three kinds of entry, mixed freely in one call:",
219
+ "(1) `{ platform }` — one of Baker's connections: an ad or data platform (Google Ads, LinkedIn Ads, Meta Ads, X Ads, Google Analytics 4, Google Search Console, Google Tag Manager), where they also pick which accounts Baker may read, or a tool (HubSpot, Google Drive, GoHighLevel, Pipedrive, Calendly, SavvyCal).",
220
+ "(2) `{ server: { name, url, auth, keyHeader, scope } }` — a remote MCP server. Use it whenever the user gives you an MCP server's address or setup instructions, or asks for any tool that is not connected: always try the vendor's real server FIRST. No address given? Find it yourself before asking the user anything — WebSearch '<vendor> MCP server', WebFetch the vendor's own docs, and take the official remote https endpoint and how it signs in from there. Fill in everything you know from their instructions — the card opens with it filled in and the user only confirms, types a key if there is one, or signs in. Never ask for a key in the chat.",
221
+ "(3) `{ app }` — the FALLBACK when the vendor has no MCP server: a managed app from `baker mcp catalog --search <name>`, which the user signs in to from the card.",
222
+ "Use it the moment a command tells you a platform isn't connected, OR that it is connected but does not allow what you asked (a `request_connection` fix, `HUBSPOT_RECONNECT_REQUIRED`, a read-only connection) — the card shows Reconnect when the connection exists. Never tell the user to go to Settings or the Integrations page instead. Each entry becomes a tab, so ask for everything the task needs in ONE call.",
127
223
  "`reason` is shown to the user: say what connecting unlocks in their terms ('so I can see which campaigns are actually converting', 'so I can count a contact becoming a customer'), never in technical terms.",
128
224
  'When the user wants a Google Drive folder\'s photos or videos in Baker, ask for `google-drive` with `choose: "media-folder"`: the card lets them pick the folder, Baker imports it as a media source (weekly by default), and the result carries its `mediaSourceKey` for `baker media-sources`. The import runs in the background — tell the user the library is filling, never that it is ready. A Drive folder is never added by link.',
225
+ "A connected app or server's tools load straight after the card resolves, in this same turn, when the result says `toolsReady: true` — call them right away (a server's tools are mcp__<name>__*, an app's ride mcp__composio_*). A server result with `problem` will not answer until a person fixes what it names; relay it plainly. `toolsReady: false` means they arrive with the user's next message — unless the server is named in `failedToLoad`: it did not answer, so say plainly it isn't working yet and never promise it for later.",
129
226
  "A declined tab is not an error — carry on with what you can do without it and say what stays unavailable. A connected result may list `cannotRead`: things the connection still does not allow — do not promise those. Results name only the account and what was selected; no credentials ever reach you.",
130
227
  ].join(" ");
131
228
  export function createConnectionInputTool() {
@@ -1 +1 @@
1
- {"version":3,"file":"connection-input.js","sourceRoot":"","sources":["../../src/hono/connection-input.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAC;AACtD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,CAAC,MAAM,0BAA0B,GAAG,mCAAmC,CAAC;AAE9E;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,YAAY;IACZ,UAAU;IACV,MAAM;IACN,kBAAkB;IAClB,uBAAuB;IACvB,oBAAoB;IACpB,OAAO;IACP,SAAS;IACT,cAAc;IACd,WAAW;IACX,WAAW;IACX,UAAU;IACV,UAAU;CACF,CAAC;AAIX,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,QAAQ,CAAC,0CAA0C,CAAC;IAC3F,MAAM,EAAE,CAAC;SACN,MAAM,EAAE;SACR,QAAQ,CAAC,+FAA+F,CAAC;IAC5G,MAAM,EAAE,CAAC;SACN,OAAO,CAAC,cAAc,CAAC;SACvB,QAAQ,EAAE;SACV,QAAQ,CACP,kMAAkM,CACnM;CACJ,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,WAAW,EAAE,CAAC;SACX,KAAK,CAAC,sBAAsB,CAAC;SAC7B,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,CAAC,wEAAwE,CAAC;IACrF,UAAU,EAAE,CAAC;SACV,MAAM,CAAC,EAAE,CAAC;SACV,QAAQ,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;SACrB,QAAQ,EAAE;SACV,QAAQ,CAAC,8FAA8F,CAAC;CAC5G,CAAC;AAEF,uDAAuD;AAEvD,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC,kBAAkB,CAAC,QAAQ,EAAE;IACxE,CAAC,CAAC,MAAM,CAAC;QACP,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;QAC9B,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC;QACtC,wDAAwD;QACxD,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QACnC,0EAA0E;QAC1E,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAC7B,6FAA6F;QAC7F,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;QAC1C,kIAAkI;QAClI,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KACtC,CAAC;IACF,CAAC,CAAC,MAAM,CAAC;QACP,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;QAC7B,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC;QACtC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAC9B,CAAC;CACH,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,2BAA2B,CAAC,EAAE,CAAC,CAAC;AAG3G,wFAAwF;AACxF,MAAM,UAAU,8BAA8B,CAAC,KAAc;IAC3D,MAAM,MAAM,GAAG,+BAA+B,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAChE,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7C,CAAC;AAID;;;;;GAKG;AACH,MAAM,UAAU,iCAAiC,CAAC,KAAc;IAC9D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,GAAG,GAAG,gBAAgB,CAAE,KAAmC,CAAC,WAAW,CAAC,CAAC;IAC/E,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,QAAQ,GAA6B,EAAE,CAAC;IAC9C,KAAK,MAAM,KAAK,IAAI,GAAG,EAAE,CAAC;QACxB,MAAM,MAAM,GAAG,sBAAsB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACvD,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACtD,SAAS;QACX,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/B,4EAA4E;QAC5E,sDAAsD;QACtD,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC;QAC3C,QAAQ,CAAC,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,QAAQ,KAAK,cAAc,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAClG,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,iCAAiC,GAAG;IACxC,4YAA4Y;IAC5Y,mZAAmZ;IACnZ,+MAA+M;IAC/M,2aAA2a;IAC3a,4SAA4S;CAC7S,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ,MAAM,UAAU,yBAAyB;IACvC,OAAO,IAAI,CACT,oBAAoB,EACpB,iCAAiC,EACjC,wBAAwB,EACxB,CAAC,IAAI,EAA+D,EAAE;QACpE,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAK,EAAE,OAAO,EAAE,EAAE,EAAuC,CAAC;QAC5F,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAC5F,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"connection-input.js","sourceRoot":"","sources":["../../src/hono/connection-input.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
  import { describe, expect, it } from "vitest";
3
- import { CONNECTION_PLATFORMS, normalizeConnectionInputToolInput, parseConnectionInputResolution, } from "./connection-input.js";
3
+ import { CONNECTION_PLATFORMS, normalizeConnectionInputToolInput, parseConnectionInputResolution, toolsConnected, } from "./connection-input.js";
4
4
  describe("normalizeConnectionInputToolInput", () => {
5
5
  it("keeps well-formed requests in the order the agent asked for them", () => {
6
6
  expect(normalizeConnectionInputToolInput({
@@ -54,6 +54,66 @@ describe("normalizeConnectionInputToolInput", () => {
54
54
  expect(normalizeConnectionInputToolInput(null)).toEqual([]);
55
55
  });
56
56
  });
57
+ describe("normalizeConnectionInputToolInput — apps and servers", () => {
58
+ it("keeps a server the user described, filled in as far as the agent knows it", () => {
59
+ expect(normalizeConnectionInputToolInput({
60
+ connections: [
61
+ {
62
+ server: { name: "acme", url: "https://acme.dev/mcp", auth: "key", keyHeader: "X-Api-Key", scope: "user" },
63
+ reason: "so I can read your Acme orders",
64
+ },
65
+ ],
66
+ })).toEqual([
67
+ {
68
+ server: { name: "acme", url: "https://acme.dev/mcp", auth: "key", keyHeader: "X-Api-Key", scope: "user" },
69
+ reason: "so I can read your Acme orders",
70
+ },
71
+ ]);
72
+ });
73
+ it("keeps an app from the catalog next to a platform", () => {
74
+ expect(normalizeConnectionInputToolInput({
75
+ connections: [
76
+ { app: "notion", reason: "so I can read your briefs" },
77
+ { platform: "hubspot", reason: "so I can count a deal won" },
78
+ ],
79
+ })).toEqual([
80
+ { app: "notion", reason: "so I can read your briefs" },
81
+ { platform: "hubspot", reason: "so I can count a deal won" },
82
+ ]);
83
+ });
84
+ it("drops a key header on a server that signs in without one, so the card never asks for a key it will not use", () => {
85
+ expect(normalizeConnectionInputToolInput({
86
+ connections: [
87
+ { server: { name: "acme", url: "https://acme.dev/mcp", auth: "none", keyHeader: "X" }, reason: "r" },
88
+ ],
89
+ })).toEqual([{ server: { name: "acme", url: "https://acme.dev/mcp", auth: "none" }, reason: "r" }]);
90
+ });
91
+ it("collapses the same app or server asked for twice into one tab", () => {
92
+ const requests = normalizeConnectionInputToolInput({
93
+ connections: [
94
+ { app: "notion", reason: "first" },
95
+ { app: "notion", reason: "second" },
96
+ { server: { name: "acme", url: "https://acme.dev/mcp" }, reason: "first" },
97
+ { server: { name: "acme", url: "https://acme.dev/mcp" }, reason: "second" },
98
+ ],
99
+ });
100
+ expect(requests.map((request) => request.reason)).toEqual(["first", "first"]);
101
+ });
102
+ });
103
+ describe("toolsConnected", () => {
104
+ it("is true when an app or a server came through, which is when the turn's tools must be reloaded", () => {
105
+ expect(toolsConnected({ results: [{ status: "connected", server: "acme", scope: "company" }] })).toBe(true);
106
+ expect(toolsConnected({ results: [{ status: "connected", app: "notion", scope: "user" }] })).toBe(true);
107
+ });
108
+ it("is false for a platform or a skipped tab, so the tool list — and the prompt cache — stay untouched", () => {
109
+ expect(toolsConnected({
110
+ results: [
111
+ { status: "connected", platform: "hubspot", selected: [] },
112
+ { status: "declined", server: "acme" },
113
+ ],
114
+ })).toBe(false);
115
+ });
116
+ });
57
117
  describe("parseConnectionInputResolution", () => {
58
118
  it("accepts a connected result carrying only the account and what was selected", () => {
59
119
  expect(parseConnectionInputResolution({
@@ -1 +1 @@
1
- {"version":3,"file":"connection-input.test.js","sourceRoot":"","sources":["../../src/hono/connection-input.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"connection-input.test.js","sourceRoot":"","sources":["../../src/hono/connection-input.test.ts"],"names":[],"mappings":"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"}
@@ -9,7 +9,14 @@ export type McpHttpServerConfig = {
9
9
  export type McpServers = Record<string, McpHttpServerConfig>;
10
10
  /** Parse and validate the /api/chat/mcp-servers response body; returns null on any mismatch. */
11
11
  export declare function parseMcpServersResponse(json: unknown): McpServers | null;
12
- export type McpServersProvider = (threadId: string, actingUserId?: string) => Promise<McpServers | undefined>;
12
+ /**
13
+ * `fresh` skips the cache for the ask that follows a mid-turn connection, and
14
+ * answers `undefined` rather than the stale set when it fails: the caller is
15
+ * asking for what is NEW, and the old set is already loaded.
16
+ */
17
+ export type McpServersProvider = (threadId: string, actingUserId?: string, options?: {
18
+ fresh?: boolean;
19
+ }) => Promise<McpServers | undefined>;
13
20
  /** Map a failed MCP server name back to its Composio scope, or null if it isn't ours. */
14
21
  export declare function composioScopeForServer(name: string): ComposioScope | null;
15
22
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-servers.d.ts","sourceRoot":"","sources":["../../src/hono/mcp-servers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAKjE,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,KAAK,CAAC;AAEpE,uFAAuF;AACvF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;AAY7D,gGAAgG;AAChG,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,IAAI,CAGxE;AAOD,MAAM,MAAM,kBAAkB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;AAS9G,yFAAyF;AACzF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAEzE;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,UAAU,GAAG,aAAa,EAAE,CAmB3E;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,EAAE,CAkB7D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,EAAE,CAarE;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE;IAAE,KAAK,EAAE,aAAa,CAAA;CAAE,GAAG;IAAE,gBAAgB,EAAE,MAAM,CAAA;CAAE,EAC/D,YAAY,CAAC,EAAE,MAAM,iBAWtB;AAED,KAAK,YAAY,GAAG;IAClB,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACjE,CAAC;AA0DF,wBAAgB,wBAAwB,CAAC,IAAI,GAAE,YAAiB,GAAG,kBAAkB,CAqBpF"}
1
+ {"version":3,"file":"mcp-servers.d.ts","sourceRoot":"","sources":["../../src/hono/mcp-servers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAKjE,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,KAAK,CAAC;AAEpE,uFAAuF;AACvF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;AAY7D,gGAAgG;AAChG,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,IAAI,CAGxE;AAcD;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAC/B,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,KAC1B,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;AASrC,yFAAyF;AACzF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAEzE;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,UAAU,GAAG,aAAa,EAAE,CAmB3E;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,EAAE,CAkB7D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,EAAE,CAarE;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE;IAAE,KAAK,EAAE,aAAa,CAAA;CAAE,GAAG;IAAE,gBAAgB,EAAE,MAAM,CAAA;CAAE,EAC/D,YAAY,CAAC,EAAE,MAAM,iBAWtB;AAED,KAAK,YAAY,GAAG;IAClB,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACjE,CAAC;AA2DF,wBAAgB,wBAAwB,CAAC,IAAI,GAAE,YAAiB,GAAG,kBAAkB,CAyBpF"}
@@ -16,6 +16,13 @@ export function parseMcpServersResponse(json) {
16
16
  }
17
17
  const FRESH_MS = 60_000;
18
18
  const FETCH_TIMEOUT_MS = 2_500;
19
+ /**
20
+ * A fresh ask follows the user connecting something mid-turn, when Convex may
21
+ * have to mint a new managed-app session — a live round-trip that regularly
22
+ * outlasts the per-turn budget. The user is watching the card, not a stalled
23
+ * turn, so it may take longer.
24
+ */
25
+ const FRESH_FETCH_TIMEOUT_MS = 20_000;
19
26
  const SCOPE_BY_ENTRY = {
20
27
  composio_user: "user",
21
28
  composio_user_org: "user_org",
@@ -149,9 +156,9 @@ async function defaultLogError(entry) {
149
156
  * teammate's turn in a shared chat must never inherit them. A chat whose sender
150
157
  * changes therefore changes tool set, and that one cache rewrite is the price.
151
158
  */
152
- async function fetchMcpServers(fetchFn, threadId, actingUserId) {
159
+ async function fetchMcpServers(fetchFn, threadId, actingUserId, timeoutMs) {
153
160
  const controller = new AbortController();
154
- const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
161
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
155
162
  try {
156
163
  const res = await fetchFn(`${env.BAKER_CONVEX_SITE_URL}/api/chat/mcp-servers`, {
157
164
  method: "POST",
@@ -177,20 +184,24 @@ export function createMcpServersProvider(deps = {}) {
177
184
  const now = deps.now ?? Date.now;
178
185
  const logError = deps.logError ?? ((entry) => void defaultLogError(entry));
179
186
  const cache = new Map();
180
- return async (threadId, actingUserId) => {
187
+ return async (threadId, actingUserId, options) => {
181
188
  const key = `${threadId}|${actingUserId ?? ""}`;
182
189
  const cached = cache.get(key);
183
- if (cached && now() - cached.fetchedAt < FRESH_MS) {
190
+ const fresh = options?.fresh === true;
191
+ if (!fresh && cached && now() - cached.fetchedAt < FRESH_MS) {
184
192
  return cached.servers;
185
193
  }
186
194
  try {
187
- const servers = await fetchMcpServers(fetchFn, threadId, actingUserId);
195
+ const timeoutMs = fresh ? FRESH_FETCH_TIMEOUT_MS : FETCH_TIMEOUT_MS;
196
+ const servers = await fetchMcpServers(fetchFn, threadId, actingUserId, timeoutMs);
197
+ // Kept for the next turn too, so it starts from the set this one reloaded
198
+ // to and the tool list — and the prompt cache — do not change twice.
188
199
  cache.set(key, { servers, fetchedAt: now() });
189
200
  return servers;
190
201
  }
191
202
  catch (error) {
192
203
  logError({ error: error instanceof Error ? error.message : String(error), threadId });
193
- return cached?.servers;
204
+ return fresh ? undefined : cached?.servers;
194
205
  }
195
206
  };
196
207
  }