@zackbart/connecta 0.8.0 → 0.9.0
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/CHANGELOG.md +128 -0
- package/README.md +31 -55
- package/SECURITY.md +5 -11
- package/dist/activity.d.ts +0 -8
- package/dist/activity.d.ts.map +1 -1
- package/dist/activity.js +0 -1
- package/dist/activity.js.map +1 -1
- package/dist/auth/bearer.d.ts +1 -7
- package/dist/auth/bearer.d.ts.map +1 -1
- package/dist/auth/bearer.js +2 -23
- package/dist/auth/bearer.js.map +1 -1
- package/dist/auth/clerk.d.ts +2 -11
- package/dist/auth/clerk.d.ts.map +1 -1
- package/dist/auth/clerk.js +31 -46
- package/dist/auth/clerk.js.map +1 -1
- package/dist/auth/downstream-oauth.d.ts +15 -6
- package/dist/auth/downstream-oauth.d.ts.map +1 -1
- package/dist/auth/downstream-oauth.js +60 -11
- package/dist/auth/downstream-oauth.js.map +1 -1
- package/dist/call-admission.d.ts.map +1 -1
- package/dist/call-admission.js +0 -1
- package/dist/call-admission.js.map +1 -1
- package/dist/catalog-service.d.ts +1 -2
- package/dist/catalog-service.d.ts.map +1 -1
- package/dist/catalog-service.js +12 -18
- package/dist/catalog-service.js.map +1 -1
- package/dist/catalog.d.ts +6 -0
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +51 -0
- package/dist/catalog.js.map +1 -1
- package/dist/connectors/remote-mcp.d.ts +1 -1
- package/dist/connectors/remote-mcp.d.ts.map +1 -1
- package/dist/connectors/remote-mcp.js +73 -71
- package/dist/connectors/remote-mcp.js.map +1 -1
- package/dist/errors.d.ts +19 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +1 -0
- package/dist/errors.js.map +1 -1
- package/dist/execute.d.ts +4 -9
- package/dist/execute.d.ts.map +1 -1
- package/dist/execute.js +41 -20
- package/dist/execute.js.map +1 -1
- package/dist/executor-result.js +1 -1
- package/dist/executor-result.js.map +1 -1
- package/dist/index.d.ts +3 -82
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -90
- package/dist/index.js.map +1 -1
- package/dist/invocation.d.ts +5 -0
- package/dist/invocation.d.ts.map +1 -1
- package/dist/invocation.js +46 -10
- package/dist/invocation.js.map +1 -1
- package/dist/meta-tools.d.ts +4 -12
- package/dist/meta-tools.d.ts.map +1 -1
- package/dist/meta-tools.js +119 -169
- package/dist/meta-tools.js.map +1 -1
- package/dist/operator-ui/generated.d.ts +2 -2
- package/dist/operator-ui/generated.d.ts.map +1 -1
- package/dist/operator-ui/generated.js +2 -2
- package/dist/operator-ui/generated.js.map +1 -1
- package/dist/operator-ui/model.d.ts +1 -22
- package/dist/operator-ui/model.d.ts.map +1 -1
- package/dist/operator-ui/model.js.map +1 -1
- package/dist/registry.d.ts +11 -178
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +52 -330
- package/dist/registry.js.map +1 -1
- package/dist/retired-toolkits.d.ts +3 -0
- package/dist/retired-toolkits.d.ts.map +1 -0
- package/dist/retired-toolkits.js +9 -0
- package/dist/retired-toolkits.js.map +1 -0
- package/dist/routes/activity.d.ts.map +1 -1
- package/dist/routes/activity.js +2 -5
- package/dist/routes/activity.js.map +1 -1
- package/dist/routes/credentials.d.ts.map +1 -1
- package/dist/routes/credentials.js +1 -12
- package/dist/routes/credentials.js.map +1 -1
- package/dist/routes/mcp.d.ts.map +1 -1
- package/dist/routes/mcp.js +94 -188
- package/dist/routes/mcp.js.map +1 -1
- package/dist/routes/oauth.d.ts.map +1 -1
- package/dist/routes/oauth.js +3 -8
- package/dist/routes/oauth.js.map +1 -1
- package/dist/routes/shared.d.ts +9 -30
- package/dist/routes/shared.d.ts.map +1 -1
- package/dist/routes/shared.js +10 -69
- package/dist/routes/shared.js.map +1 -1
- package/dist/routes/ui.d.ts.map +1 -1
- package/dist/routes/ui.js +4 -10
- package/dist/routes/ui.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1 -31
- package/dist/server.js.map +1 -1
- package/dist/skills.d.ts +3 -6
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +9 -38
- package/dist/skills.js.map +1 -1
- package/dist/timeout.d.ts.map +1 -1
- package/dist/timeout.js +2 -4
- package/dist/timeout.js.map +1 -1
- package/dist/types.d.ts +8 -61
- package/dist/types.d.ts.map +1 -1
- package/dist/ui.d.ts +1 -2
- package/dist/ui.d.ts.map +1 -1
- package/dist/ui.js +5 -35
- package/dist/ui.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -2
- package/src/activity.ts +0 -9
- package/src/auth/bearer.ts +3 -32
- package/src/auth/clerk.ts +35 -48
- package/src/auth/downstream-oauth.ts +106 -24
- package/src/call-admission.ts +0 -1
- package/src/catalog-service.ts +23 -23
- package/src/catalog.ts +55 -0
- package/src/connectors/remote-mcp.ts +106 -86
- package/src/errors.ts +22 -0
- package/src/execute.ts +43 -24
- package/src/executor-result.ts +1 -1
- package/src/index.ts +24 -208
- package/src/invocation.ts +63 -10
- package/src/meta-tools.ts +139 -187
- package/src/operator-ui/browser.css +1 -54
- package/src/operator-ui/browser.ts +16 -150
- package/src/operator-ui/generated.ts +2 -2
- package/src/operator-ui/model.ts +1 -23
- package/src/registry.ts +59 -429
- package/src/retired-toolkits.ts +14 -0
- package/src/routes/activity.ts +1 -6
- package/src/routes/credentials.ts +0 -12
- package/src/routes/mcp.ts +110 -230
- package/src/routes/oauth.ts +2 -8
- package/src/routes/shared.ts +10 -100
- package/src/routes/ui.ts +2 -12
- package/src/server.ts +1 -31
- package/src/skills.ts +9 -38
- package/src/timeout.ts +2 -4
- package/src/types.ts +11 -62
- package/src/ui.ts +9 -46
- package/src/version.ts +1 -1
- package/dist/credential-health.d.ts +0 -205
- package/dist/credential-health.d.ts.map +0 -1
- package/dist/credential-health.js +0 -610
- package/dist/credential-health.js.map +0 -1
- package/dist/toolkits.d.ts +0 -124
- package/dist/toolkits.d.ts.map +0 -1
- package/dist/toolkits.js +0 -322
- package/dist/toolkits.js.map +0 -1
- package/src/credential-health.ts +0 -835
- package/src/toolkits.ts +0 -461
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import type { OAuthClientProvider } from "@modelcontextprotocol/sdk/client/auth.js";
|
|
2
1
|
import type {
|
|
2
|
+
OAuthClientInformationContext,
|
|
3
3
|
OAuthClientInformationMixed,
|
|
4
4
|
OAuthClientMetadata,
|
|
5
|
+
OAuthClientProvider,
|
|
5
6
|
OAuthTokens,
|
|
6
|
-
} from "@modelcontextprotocol/
|
|
7
|
+
} from "@modelcontextprotocol/client";
|
|
7
8
|
import type { KVStorage } from "../types.js";
|
|
8
9
|
|
|
9
10
|
/** A 256-bit random opaque value, hex-encoded — used for the OAuth `state`. */
|
|
@@ -25,7 +26,7 @@ const LEGACY_GENERATION = "legacy";
|
|
|
25
26
|
const ACTIVE_GENERATION_PREFIX = "v2:";
|
|
26
27
|
const RESETTING_GENERATION_PREFIX = "reset:";
|
|
27
28
|
const DISCONNECTED_GENERATION_PREFIX = "disconnected:";
|
|
28
|
-
const STORED_VALUE_VERSION =
|
|
29
|
+
const STORED_VALUE_VERSION = 2;
|
|
29
30
|
const OAUTH_VALUE_KEYS = [
|
|
30
31
|
"oauth:client",
|
|
31
32
|
"oauth:tokens",
|
|
@@ -38,6 +39,13 @@ const MAX_CLEANUP_BACKLOG = 1_000;
|
|
|
38
39
|
interface StoredOAuthValue<T> {
|
|
39
40
|
connectaOAuthVersion: typeof STORED_VALUE_VERSION;
|
|
40
41
|
generation: string;
|
|
42
|
+
issuer?: string;
|
|
43
|
+
value: T;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
interface LegacyStoredOAuthValue<T> {
|
|
47
|
+
connectaOAuthVersion: 1;
|
|
48
|
+
generation: string;
|
|
41
49
|
value: T;
|
|
42
50
|
}
|
|
43
51
|
|
|
@@ -49,6 +57,19 @@ function storedOAuthValue<T>(
|
|
|
49
57
|
return (
|
|
50
58
|
candidate.connectaOAuthVersion === STORED_VALUE_VERSION &&
|
|
51
59
|
typeof candidate.generation === "string" &&
|
|
60
|
+
(candidate.issuer === undefined || typeof candidate.issuer === "string") &&
|
|
61
|
+
"value" in candidate
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function legacyStoredOAuthValue<T>(
|
|
66
|
+
value: unknown,
|
|
67
|
+
): value is LegacyStoredOAuthValue<T> {
|
|
68
|
+
if (!value || typeof value !== "object") return false;
|
|
69
|
+
const candidate = value as Partial<LegacyStoredOAuthValue<T>>;
|
|
70
|
+
return (
|
|
71
|
+
candidate.connectaOAuthVersion === 1 &&
|
|
72
|
+
typeof candidate.generation === "string" &&
|
|
52
73
|
"value" in candidate
|
|
53
74
|
);
|
|
54
75
|
}
|
|
@@ -132,6 +153,7 @@ export class KvOAuthProvider implements OAuthClientProvider {
|
|
|
132
153
|
key: string,
|
|
133
154
|
value: T,
|
|
134
155
|
serializeLegacy: (value: T) => string,
|
|
156
|
+
issuer?: string,
|
|
135
157
|
): Promise<void> {
|
|
136
158
|
const generation = await this.writeGeneration();
|
|
137
159
|
if (
|
|
@@ -144,12 +166,13 @@ export class KvOAuthProvider implements OAuthClientProvider {
|
|
|
144
166
|
const stored: StoredOAuthValue<T> = {
|
|
145
167
|
connectaOAuthVersion: STORED_VALUE_VERSION,
|
|
146
168
|
generation,
|
|
169
|
+
...(issuer !== undefined ? { issuer } : {}),
|
|
147
170
|
value,
|
|
148
171
|
};
|
|
149
172
|
const physicalKey = oauthValueStorageKey(key, generation);
|
|
150
173
|
await this.storage.set(
|
|
151
174
|
physicalKey,
|
|
152
|
-
isModernGeneration(generation)
|
|
175
|
+
isModernGeneration(generation) || issuer !== undefined
|
|
153
176
|
? JSON.stringify(stored)
|
|
154
177
|
: serializeLegacy(value),
|
|
155
178
|
);
|
|
@@ -182,7 +205,9 @@ export class KvOAuthProvider implements OAuthClientProvider {
|
|
|
182
205
|
private async readValue<T>(
|
|
183
206
|
key: string,
|
|
184
207
|
parseLegacy: (raw: string) => T,
|
|
185
|
-
): Promise<
|
|
208
|
+
): Promise<
|
|
209
|
+
{ value: T; generation: string; issuer?: string } | undefined
|
|
210
|
+
> {
|
|
186
211
|
const generation = await this.generation();
|
|
187
212
|
const raw = await this.storage.get(
|
|
188
213
|
oauthValueStorageKey(key, generation),
|
|
@@ -202,6 +227,15 @@ export class KvOAuthProvider implements OAuthClientProvider {
|
|
|
202
227
|
// Raw string state from a pre-envelope deployment is handled below.
|
|
203
228
|
}
|
|
204
229
|
if (storedOAuthValue<T>(parsed)) {
|
|
230
|
+
return parsed.generation === generation
|
|
231
|
+
? {
|
|
232
|
+
value: parsed.value,
|
|
233
|
+
generation,
|
|
234
|
+
...(parsed.issuer !== undefined ? { issuer: parsed.issuer } : {}),
|
|
235
|
+
}
|
|
236
|
+
: undefined;
|
|
237
|
+
}
|
|
238
|
+
if (legacyStoredOAuthValue<T>(parsed)) {
|
|
205
239
|
return parsed.generation === generation
|
|
206
240
|
? { value: parsed.value, generation }
|
|
207
241
|
: undefined;
|
|
@@ -210,6 +244,40 @@ export class KvOAuthProvider implements OAuthClientProvider {
|
|
|
210
244
|
return { value: parseLegacy(raw), generation };
|
|
211
245
|
}
|
|
212
246
|
|
|
247
|
+
/**
|
|
248
|
+
* Read credentials only for the authorization server that issued them.
|
|
249
|
+
*
|
|
250
|
+
* Values written before issuer binding are bound on their first read with a
|
|
251
|
+
* validated SDK issuer, preserving an existing grant across this upgrade.
|
|
252
|
+
* A later issuer change is different: publish a new generation before
|
|
253
|
+
* returning no credentials, so every isolate drops the old registration and
|
|
254
|
+
* token set and the SDK starts authorization from scratch.
|
|
255
|
+
*/
|
|
256
|
+
private async readIssuerBoundValue<T>(
|
|
257
|
+
key: "oauth:client" | "oauth:tokens",
|
|
258
|
+
parseLegacy: (raw: string) => T,
|
|
259
|
+
serializeLegacy: (value: T) => string,
|
|
260
|
+
ctx?: OAuthClientInformationContext,
|
|
261
|
+
): Promise<T | undefined> {
|
|
262
|
+
const stored = await this.readValue(key, parseLegacy);
|
|
263
|
+
if (!stored || !ctx) return stored?.value;
|
|
264
|
+
if (stored.issuer === undefined) {
|
|
265
|
+
await this.writeValue(key, stored.value, serializeLegacy, ctx.issuer);
|
|
266
|
+
return stored.value;
|
|
267
|
+
}
|
|
268
|
+
if (stored.issuer === ctx.issuer) return stored.value;
|
|
269
|
+
|
|
270
|
+
try {
|
|
271
|
+
await this.resetAuthorization();
|
|
272
|
+
} finally {
|
|
273
|
+
// The issuer-aware flow may continue after the reset. Stamp any later
|
|
274
|
+
// writes into the replacement epoch; the connector's generation check
|
|
275
|
+
// still discards this connection attempt before caching it.
|
|
276
|
+
this.captureGeneration(await this.generation());
|
|
277
|
+
}
|
|
278
|
+
return undefined;
|
|
279
|
+
}
|
|
280
|
+
|
|
213
281
|
/** Attempt every key deletion, then report the first backend failure. */
|
|
214
282
|
private async deleteAll(keys: readonly string[]): Promise<void> {
|
|
215
283
|
let firstError: unknown;
|
|
@@ -276,35 +344,49 @@ export class KvOAuthProvider implements OAuthClientProvider {
|
|
|
276
344
|
};
|
|
277
345
|
}
|
|
278
346
|
|
|
279
|
-
async clientInformation(
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
)
|
|
285
|
-
|
|
347
|
+
async clientInformation(
|
|
348
|
+
ctx?: OAuthClientInformationContext,
|
|
349
|
+
): Promise<OAuthClientInformationMixed | undefined> {
|
|
350
|
+
return this.readIssuerBoundValue(
|
|
351
|
+
"oauth:client",
|
|
352
|
+
(raw) => JSON.parse(raw) as OAuthClientInformationMixed,
|
|
353
|
+
(value) => JSON.stringify(value),
|
|
354
|
+
ctx,
|
|
355
|
+
);
|
|
286
356
|
}
|
|
287
357
|
|
|
288
358
|
async saveClientInformation(
|
|
289
359
|
info: OAuthClientInformationMixed,
|
|
360
|
+
ctx?: OAuthClientInformationContext,
|
|
290
361
|
): Promise<void> {
|
|
291
|
-
await this.writeValue(
|
|
292
|
-
|
|
362
|
+
await this.writeValue(
|
|
363
|
+
"oauth:client",
|
|
364
|
+
info,
|
|
365
|
+
(value) => JSON.stringify(value),
|
|
366
|
+
ctx?.issuer,
|
|
293
367
|
);
|
|
294
368
|
}
|
|
295
369
|
|
|
296
|
-
async tokens(
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
)
|
|
302
|
-
|
|
370
|
+
async tokens(
|
|
371
|
+
ctx?: OAuthClientInformationContext,
|
|
372
|
+
): Promise<OAuthTokens | undefined> {
|
|
373
|
+
return this.readIssuerBoundValue(
|
|
374
|
+
"oauth:tokens",
|
|
375
|
+
(raw) => JSON.parse(raw) as OAuthTokens,
|
|
376
|
+
(value) => JSON.stringify(value),
|
|
377
|
+
ctx,
|
|
378
|
+
);
|
|
303
379
|
}
|
|
304
380
|
|
|
305
|
-
async saveTokens(
|
|
306
|
-
|
|
307
|
-
|
|
381
|
+
async saveTokens(
|
|
382
|
+
tokens: OAuthTokens,
|
|
383
|
+
ctx?: OAuthClientInformationContext,
|
|
384
|
+
): Promise<void> {
|
|
385
|
+
await this.writeValue(
|
|
386
|
+
"oauth:tokens",
|
|
387
|
+
tokens,
|
|
388
|
+
(value) => JSON.stringify(value),
|
|
389
|
+
ctx?.issuer,
|
|
308
390
|
);
|
|
309
391
|
}
|
|
310
392
|
|
package/src/call-admission.ts
CHANGED
package/src/catalog-service.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
compactSchema,
|
|
3
|
+
lexicalSearchQuery,
|
|
4
|
+
rankTools,
|
|
5
|
+
summarizeDescription,
|
|
6
|
+
} from "./catalog.js";
|
|
2
7
|
import {
|
|
3
8
|
mapSettledWithConcurrency,
|
|
4
9
|
resolveDiscoveryConcurrency,
|
|
@@ -20,10 +25,11 @@ import {
|
|
|
20
25
|
} from "./timeout.js";
|
|
21
26
|
import type {
|
|
22
27
|
Connector,
|
|
28
|
+
JsonSchema,
|
|
23
29
|
ToolDef,
|
|
24
30
|
} from "./types.js";
|
|
25
31
|
|
|
26
|
-
const DEFAULT_SEARCH_LIMIT =
|
|
32
|
+
export const DEFAULT_SEARCH_LIMIT = 8;
|
|
27
33
|
export const MAX_SEARCH_LIMIT = 100;
|
|
28
34
|
export const MAX_DESCRIBE_ADDRESSES = 100;
|
|
29
35
|
export const MAX_DISCOVERY_RESULT_BYTES = 256_000;
|
|
@@ -76,7 +82,7 @@ function discoveryAddresses(value: unknown): unknown[] {
|
|
|
76
82
|
|
|
77
83
|
/** Serialize once and count the exact bytes the MCP adapter would emit. */
|
|
78
84
|
export function boundedDiscoveryText(value: unknown, hint: string): string {
|
|
79
|
-
const text = JSON.stringify(value
|
|
85
|
+
const text = JSON.stringify(value);
|
|
80
86
|
if (text === undefined) {
|
|
81
87
|
throw new TypeError("Discovery result is not JSON-serializable.");
|
|
82
88
|
}
|
|
@@ -90,14 +96,6 @@ export function boundedDiscoveryText(value: unknown, hint: string): string {
|
|
|
90
96
|
return text;
|
|
91
97
|
}
|
|
92
98
|
|
|
93
|
-
/** Apply the same final UTF-8 boundary where only the check is needed. */
|
|
94
|
-
export function assertDiscoveryResultSize(
|
|
95
|
-
value: unknown,
|
|
96
|
-
hint: string,
|
|
97
|
-
): void {
|
|
98
|
-
boundedDiscoveryText(value, hint);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
99
|
export interface CatalogSearchArgs {
|
|
102
100
|
query?: string;
|
|
103
101
|
connector?: string;
|
|
@@ -172,6 +170,10 @@ function framingError(code: string, message: string): CallErrorDetails {
|
|
|
172
170
|
return { code, message, retryable: messageLooksRetryable(message) };
|
|
173
171
|
}
|
|
174
172
|
|
|
173
|
+
function renderSchema(schema: JsonSchema, format: "compact" | "json"): unknown {
|
|
174
|
+
return format === "json" ? schema : compactSchema(schema);
|
|
175
|
+
}
|
|
176
|
+
|
|
175
177
|
/**
|
|
176
178
|
* Request-local catalog operations shared by MCP meta-tools and code mode.
|
|
177
179
|
* Successful catalogs may be reused inside this request; failures are not
|
|
@@ -365,6 +367,7 @@ export class CatalogService {
|
|
|
365
367
|
|
|
366
368
|
async search(args: CatalogSearchArgs): Promise<CatalogSearchPage> {
|
|
367
369
|
const query = args.query ?? "";
|
|
370
|
+
const retrievalQuery = lexicalSearchQuery(query);
|
|
368
371
|
const limit = discoverySearchLimit(args.limit);
|
|
369
372
|
const offset = Math.max(0, Math.trunc(args.offset ?? 0));
|
|
370
373
|
const connectors = args.connector
|
|
@@ -397,7 +400,11 @@ export class CatalogService {
|
|
|
397
400
|
throw new Error("Catalog result has no corresponding connector");
|
|
398
401
|
}
|
|
399
402
|
if (catalog.status === "fulfilled") {
|
|
400
|
-
for (const ranked of rankTools(
|
|
403
|
+
for (const ranked of rankTools(
|
|
404
|
+
catalog.value,
|
|
405
|
+
retrievalQuery,
|
|
406
|
+
mode,
|
|
407
|
+
)) {
|
|
401
408
|
matches.push({
|
|
402
409
|
connector,
|
|
403
410
|
tool: ranked.tool,
|
|
@@ -434,17 +441,13 @@ export class CatalogService {
|
|
|
434
441
|
...(args.includeSchemas
|
|
435
442
|
? {
|
|
436
443
|
inputSchema:
|
|
437
|
-
args.includeSchemas
|
|
438
|
-
? input
|
|
439
|
-
: compactSchema(input),
|
|
444
|
+
renderSchema(input, args.includeSchemas),
|
|
440
445
|
}
|
|
441
446
|
: {}),
|
|
442
447
|
...(args.includeSchemas && match.tool.outputSchema
|
|
443
448
|
? {
|
|
444
449
|
outputSchema:
|
|
445
|
-
args.includeSchemas
|
|
446
|
-
? match.tool.outputSchema
|
|
447
|
-
: compactSchema(match.tool.outputSchema),
|
|
450
|
+
renderSchema(match.tool.outputSchema, args.includeSchemas),
|
|
448
451
|
}
|
|
449
452
|
: {}),
|
|
450
453
|
...(match.tool.annotations
|
|
@@ -534,13 +537,10 @@ export class CatalogService {
|
|
|
534
537
|
...(connectorGuide(addressResolution.connector)
|
|
535
538
|
? { guide: connectorSkillName(addressResolution.connector.id) }
|
|
536
539
|
: {}),
|
|
537
|
-
inputSchema:
|
|
540
|
+
inputSchema: renderSchema(input, format),
|
|
538
541
|
...(tool.outputSchema
|
|
539
542
|
? {
|
|
540
|
-
outputSchema:
|
|
541
|
-
format === "json"
|
|
542
|
-
? tool.outputSchema
|
|
543
|
-
: compactSchema(tool.outputSchema),
|
|
543
|
+
outputSchema: renderSchema(tool.outputSchema, format),
|
|
544
544
|
}
|
|
545
545
|
: {}),
|
|
546
546
|
...(tool.annotations ? { annotations: tool.annotations } : {}),
|
package/src/catalog.ts
CHANGED
|
@@ -17,6 +17,61 @@ function normalized(text: string): string {
|
|
|
17
17
|
return text.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Conversational framing selected by the #188 research run before the #189
|
|
22
|
+
* holdout existed. Action-bearing terms such as get/list/search/find/create
|
|
23
|
+
* deliberately remain: arbitrary connector catalogs need those distinctions.
|
|
24
|
+
*/
|
|
25
|
+
const CONVERSATIONAL_QUERY_WORDS = new Set([
|
|
26
|
+
"a",
|
|
27
|
+
"all",
|
|
28
|
+
"an",
|
|
29
|
+
"and",
|
|
30
|
+
"are",
|
|
31
|
+
"can",
|
|
32
|
+
"could",
|
|
33
|
+
"current",
|
|
34
|
+
"for",
|
|
35
|
+
"from",
|
|
36
|
+
"i",
|
|
37
|
+
"in",
|
|
38
|
+
"into",
|
|
39
|
+
"it",
|
|
40
|
+
"latest",
|
|
41
|
+
"let",
|
|
42
|
+
"me",
|
|
43
|
+
"most",
|
|
44
|
+
"of",
|
|
45
|
+
"on",
|
|
46
|
+
"our",
|
|
47
|
+
"please",
|
|
48
|
+
"right",
|
|
49
|
+
"show",
|
|
50
|
+
"that",
|
|
51
|
+
"the",
|
|
52
|
+
"this",
|
|
53
|
+
"to",
|
|
54
|
+
"up",
|
|
55
|
+
"want",
|
|
56
|
+
"when",
|
|
57
|
+
"which",
|
|
58
|
+
"with",
|
|
59
|
+
"you",
|
|
60
|
+
]);
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Remove conversational framing before the all-term/partial decision. If
|
|
64
|
+
* every term is framing, retain the original query rather than turning a
|
|
65
|
+
* search into an unfiltered catalog browse.
|
|
66
|
+
*/
|
|
67
|
+
export function lexicalSearchQuery(query: string): string {
|
|
68
|
+
const terms = normalized(query).split(/\s+/).filter(Boolean);
|
|
69
|
+
const contentTerms = terms.filter(
|
|
70
|
+
(term) => !CONVERSATIONAL_QUERY_WORDS.has(term),
|
|
71
|
+
);
|
|
72
|
+
return contentTerms.length > 0 ? contentTerms.join(" ") : query;
|
|
73
|
+
}
|
|
74
|
+
|
|
20
75
|
interface SearchDocument {
|
|
21
76
|
tool: ToolDef;
|
|
22
77
|
name: string;
|