@zackbart/connecta 0.24.4 → 0.25.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/AGENTS.md +40 -10
- package/CHANGELOG.md +253 -0
- package/dist/advertised-schema.js +53 -0
- package/dist/auth/downstream-oauth.js +490 -106
- package/dist/call-admission.js +139 -113
- package/dist/catalog-service.js +141 -105
- package/dist/catalog.js +258 -33
- package/dist/concurrency.js +24 -23
- package/dist/connector-scope.js +6 -37
- package/dist/connectors/api.d.ts +2 -2
- package/dist/connectors/remote-mcp.d.ts +6 -5
- package/dist/connectors/remote-mcp.js +317 -241
- package/dist/credential-contract.d.ts +9 -0
- package/dist/credential-rules.js +2 -2
- package/dist/credentials.d.ts +6 -1
- package/dist/credentials.js +45 -3
- package/dist/execute.js +363 -257
- package/dist/executor-admission.js +67 -50
- package/dist/executors/quickjs-runtime.js +4 -2
- package/dist/executors/quickjs.js +251 -210
- package/dist/fix-prompt.js +37 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.js +51 -20
- package/dist/invocation.js +324 -285
- package/dist/meta-tools.js +206 -92
- package/dist/oauth-callback-outcome.js +94 -0
- package/dist/oauth-sealing.js +29 -0
- package/dist/operator-ui/fix-prompts.js +87 -0
- package/dist/operator-ui/generated.js +2 -2
- package/dist/operator-ui/model.d.ts +46 -1
- package/dist/operator-ui/setup-commands.js +53 -0
- package/dist/operator-ui/view.js +38 -2
- package/dist/program-source.js +205 -0
- package/dist/providers/notion.js +2 -2
- package/dist/providers/revenuecat.js +32 -5
- package/dist/providers/stripe.d.ts +3 -2
- package/dist/providers/vercel.js +1 -1
- package/dist/registry.d.ts +1 -1
- package/dist/registry.js +305 -260
- package/dist/routes/activity.js +120 -137
- package/dist/routes/credentials.js +174 -163
- package/dist/routes/mcp.js +129 -70
- package/dist/routes/oauth-management.js +60 -71
- package/dist/routes/oauth.js +44 -16
- package/dist/routes/operator.js +82 -0
- package/dist/routes/shared.d.ts +2 -0
- package/dist/routes/ui-data.js +210 -0
- package/dist/routes/ui.js +64 -32
- package/dist/runtime/admission.js +43 -0
- package/dist/runtime/call-admission.js +67 -0
- package/dist/runtime/connector-scope.js +72 -0
- package/dist/runtime/run.js +174 -0
- package/dist/runtime/services.js +130 -0
- package/dist/runtime/storage.js +66 -0
- package/dist/server.js +111 -89
- package/dist/skills.js +1 -1
- package/dist/storage/file.js +39 -2
- package/dist/storage/memory.js +28 -16
- package/dist/timeout.js +17 -47
- package/dist/types.d.ts +27 -7
- package/dist/ui.d.ts +16 -2
- package/dist/ui.js +50 -166
- package/dist/url-safety.js +157 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/documentation/architecture.md +184 -10
- package/documentation/auth.md +80 -0
- package/documentation/code-mode.md +69 -24
- package/documentation/meta-tools.md +164 -27
- package/ethos.md +44 -47
- package/examples/worker/README.md +51 -5
- package/examples/worker/src/d1-storage.ts +116 -0
- package/examples/worker/src/index.ts +6 -6
- package/examples/worker/wrangler.jsonc +16 -4
- package/package.json +11 -3
- package/templates/node/package.json +1 -1
- package/dist/auth/downstream-oauth.d.ts +0 -200
- package/dist/catalog-fingerprint.d.ts +0 -19
- package/dist/catalog-limits.d.ts +0 -9
- package/dist/catalog-service.d.ts +0 -263
- package/dist/catalog.d.ts +0 -87
- package/dist/concurrency.d.ts +0 -3
- package/dist/connectors/guarded-fetch.d.ts +0 -96
- package/dist/credential-rules.d.ts +0 -85
- package/dist/execute.d.ts +0 -154
- package/dist/executor-result.d.ts +0 -10
- package/dist/executors/quickjs-child.d.ts +0 -1
- package/dist/executors/quickjs-protocol.d.ts +0 -67
- package/dist/favicon.d.ts +0 -1
- package/dist/identity.d.ts +0 -4
- package/dist/invocation.d.ts +0 -74
- package/dist/mcp-result.d.ts +0 -8
- package/dist/meta-tools.d.ts +0 -129
- package/dist/operator-ui/generated.d.ts +0 -2
- package/dist/operator-ui/view.d.ts +0 -188
- package/dist/result-shapes.d.ts +0 -13
- package/dist/retired-toolkits.d.ts +0 -2
- package/dist/routes/activity.d.ts +0 -2
- package/dist/routes/credentials.d.ts +0 -2
- package/dist/routes/mcp.d.ts +0 -10
- package/dist/routes/oauth-management.d.ts +0 -2
- package/dist/routes/oauth.d.ts +0 -2
- package/dist/routes/ui.d.ts +0 -2
- package/dist/server.d.ts +0 -9
- package/dist/skills.d.ts +0 -44
- package/dist/timeout.d.ts +0 -21
- package/dist/tool-safety.d.ts +0 -9
|
@@ -27,15 +27,27 @@
|
|
|
27
27
|
{ "binding": "CONNECTA_KV", "id": "replace-with-kv-namespace-id" }
|
|
28
28
|
],
|
|
29
29
|
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
30
|
+
// D1 databases, off by default so this example deploys without one.
|
|
31
|
+
// Uncomment the array and keep the entries you use.
|
|
32
|
+
//
|
|
33
|
+
// ACTIVITY_DB: activity history. Create with `wrangler d1 create
|
|
34
|
+
// connecta-activity`, paste the id, apply the schema in README.md, then
|
|
35
|
+
// uncomment the matching lines in src/index.ts.
|
|
36
|
+
//
|
|
37
|
+
// STORAGE_DB: strongly consistent storage with compare-and-set, in place of
|
|
38
|
+
// CONNECTA_KV. Create with `wrangler d1 create connecta-storage`, paste the
|
|
39
|
+
// id, apply the schema in README.md § "Strongly consistent storage", then
|
|
40
|
+
// pass `d1Storage(env.STORAGE_DB)` as `storage` in src/index.ts.
|
|
34
41
|
// "d1_databases": [
|
|
35
42
|
// {
|
|
36
43
|
// "binding": "ACTIVITY_DB",
|
|
37
44
|
// "database_name": "connecta-activity",
|
|
38
45
|
// "database_id": "replace-with-d1-database-id"
|
|
46
|
+
// },
|
|
47
|
+
// {
|
|
48
|
+
// "binding": "STORAGE_DB",
|
|
49
|
+
// "database_name": "connecta-storage",
|
|
50
|
+
// "database_id": "replace-with-d1-database-id"
|
|
39
51
|
// }
|
|
40
52
|
// ],
|
|
41
53
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zackbart/connecta",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "One MCP to rule them all — a single MCP endpoint aggregating many downstream connectors behind a code-first surface of seven meta-tools.",
|
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
"clean": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
117
117
|
"build:operator-ui": "node scripts/build-operator-ui.mjs",
|
|
118
118
|
"check:operator-ui": "node scripts/build-operator-ui.mjs --check",
|
|
119
|
-
"build": "npm run build:operator-ui && npm run clean && tsc -p tsconfig.build.json",
|
|
119
|
+
"build": "npm run build:operator-ui && npm run clean && tsc -p tsconfig.build.json && node scripts/prune-declarations.mjs",
|
|
120
120
|
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.operator-ui.json --noEmit",
|
|
121
121
|
"test": "vitest run",
|
|
122
122
|
"test:browser:install": "playwright install chromium",
|
|
@@ -129,9 +129,16 @@
|
|
|
129
129
|
"check:examples": "tsc -p tsconfig.template.node.json && tsc -p tsconfig.examples.worker.json",
|
|
130
130
|
"check:security": "npm audit --omit=dev --audit-level=moderate",
|
|
131
131
|
"check:package": "node scripts/check-package.mjs",
|
|
132
|
+
"check:declarations": "node scripts/check-declarations.mjs --dist .",
|
|
133
|
+
"check:bundle": "node scripts/bundle-size.mjs",
|
|
132
134
|
"providers:check": "tsx scripts/drift-check.mjs --specs --docs",
|
|
133
135
|
"drift:check": "tsx scripts/drift-check.mjs",
|
|
134
|
-
"
|
|
136
|
+
"eval:selftest": "tsx eval/selftest.ts",
|
|
137
|
+
"eval:agent": "tsx eval/run-agent.ts",
|
|
138
|
+
"eval:smoke": "tsx eval/run-smoke.ts",
|
|
139
|
+
"eval:perf": "tsx eval/run-perf.ts",
|
|
140
|
+
"eval:report": "tsx eval/report.ts",
|
|
141
|
+
"check": "npm run check:docs && npm run check:operator-ui && npm run check:lint && npm run check:unused && npm run typecheck && npm run test && npm run test:browser && npm run build && npm run check:declarations && npm run check:bundle && npm run check:examples",
|
|
135
142
|
"release:check": "npm run check && npm run check:security && npm run check:package",
|
|
136
143
|
"prepack": "npm run check"
|
|
137
144
|
},
|
|
@@ -139,6 +146,7 @@
|
|
|
139
146
|
"@cfworker/json-schema": "^4.1.1",
|
|
140
147
|
"@modelcontextprotocol/client": "2.0.0",
|
|
141
148
|
"@modelcontextprotocol/server": "2.0.0",
|
|
149
|
+
"effect": "4.0.0-rc.117",
|
|
142
150
|
"zod": "^4.4.3"
|
|
143
151
|
},
|
|
144
152
|
"peerDependencies": {
|
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import type { FetchLike, OAuthClientInformationContext, OAuthClientInformationMixed, OAuthClientMetadata, OAuthClientProvider, OAuthDiscoveryState, OAuthTokens } from "@modelcontextprotocol/client";
|
|
2
|
-
import type { KVStorage } from "../types.js";
|
|
3
|
-
type OAuthRefreshFlightOutcome = {
|
|
4
|
-
status: "refreshed";
|
|
5
|
-
} | {
|
|
6
|
-
status: "retired";
|
|
7
|
-
} | {
|
|
8
|
-
status: "failed";
|
|
9
|
-
error: unknown;
|
|
10
|
-
};
|
|
11
|
-
interface OAuthRefreshFlight {
|
|
12
|
-
done: Promise<OAuthRefreshFlightOutcome>;
|
|
13
|
-
release: (outcome: OAuthRefreshFlightOutcome) => void;
|
|
14
|
-
stopObservingOwnerAbort: () => void;
|
|
15
|
-
mutationId: object;
|
|
16
|
-
writing: boolean;
|
|
17
|
-
/**
|
|
18
|
-
* Set once the token endpoint answered with valid tokens: the authorization
|
|
19
|
-
* server has consumed the rotating refresh token, so if the SDK's own
|
|
20
|
-
* saveTokens never arrives (owner cancelled, redirected, or invalidated),
|
|
21
|
-
* `fail` persists this copy itself rather than stranding the marker or
|
|
22
|
-
* letting a contender redeem the retired token.
|
|
23
|
-
*/
|
|
24
|
-
acceptedTokens?: OAuthTokens;
|
|
25
|
-
persist?: (tokens: OAuthTokens) => Promise<void>;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Share one rotating-token redemption within one connector runtime and OAuth
|
|
29
|
-
* generation. The first request still owns the real fetch and response. Its
|
|
30
|
-
* abort signal has one bounded listener until the exact flight settles, so a
|
|
31
|
-
* cancellation after the response cannot strand waiters during token storage.
|
|
32
|
-
* Followers wait for that provider to save tokens, then re-read storage. The
|
|
33
|
-
* map never retains a token response or transport.
|
|
34
|
-
*
|
|
35
|
-
* This is intentionally runtime-local. KVStorage has no atomic coordination
|
|
36
|
-
* operation, so a second isolate can still race the same refresh token.
|
|
37
|
-
*/
|
|
38
|
-
export declare class OAuthRefreshCoordinator {
|
|
39
|
-
private readonly flights;
|
|
40
|
-
/** Opaque identities only: no request promise, signal, callback, or response. */
|
|
41
|
-
private readonly pendingMutations;
|
|
42
|
-
/** One bounded latest-success slot, containing only generation + identity. */
|
|
43
|
-
private successfulRefresh;
|
|
44
|
-
/** Replaced on every map mutation, closing flight/pending ABA across awaits. */
|
|
45
|
-
private stateRevision;
|
|
46
|
-
private advanceStateRevision;
|
|
47
|
-
private observeAuthoritativeGeneration;
|
|
48
|
-
private settle;
|
|
49
|
-
private markMutationPending;
|
|
50
|
-
private finishMutation;
|
|
51
|
-
/** @internal Opaque basis for issuer-aware provider token reads. */
|
|
52
|
-
successfulRefreshIdentity(generation: string): object | undefined;
|
|
53
|
-
coordinatedFetch(provider: KvOAuthProvider, baseFetch: FetchLike, requestSignal?: AbortSignal): FetchLike;
|
|
54
|
-
/** Start storage only while this owner still holds its exact flight. */
|
|
55
|
-
beginMutation(generation: string, flight: OAuthRefreshFlight): boolean;
|
|
56
|
-
/** Publish one exact owner's successful save without disturbing a newer try. */
|
|
57
|
-
succeedMutation(generation: string, flight: OAuthRefreshFlight): void;
|
|
58
|
-
/** Give joined callers a fetch/flow failure, without rejecting the gate. */
|
|
59
|
-
fail(generation: string, flight: OAuthRefreshFlight, error: unknown): void;
|
|
60
|
-
/** Finish an exact failed credential write, then publish its failure. */
|
|
61
|
-
failMutation(generation: string, flight: OAuthRefreshFlight, error: unknown): void;
|
|
62
|
-
/** Force reauthorization fences and wakes every waiter on the retired epoch. */
|
|
63
|
-
retire(generation: string): void;
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Physical key for an OAuth value in one authorization epoch. Legacy values
|
|
67
|
-
* keep their historical names so upgrades can read an existing grant. Modern
|
|
68
|
-
* values get an epoch-specific namespace: a stale write or delete can then
|
|
69
|
-
* affect only its own flow, even if it lands after a replacement flow.
|
|
70
|
-
*/
|
|
71
|
-
export declare function oauthValueStorageKey(key: string, generation: string | null): string;
|
|
72
|
-
/**
|
|
73
|
-
* OAuthClientProvider implemented over KVStorage for a single downstream
|
|
74
|
-
* connector. Keys live in the connector's namespace as `oauth:<field>`.
|
|
75
|
-
*
|
|
76
|
-
* Headless twist: redirectToAuthorization() cannot navigate a user agent, so it
|
|
77
|
-
* STORES the authorization URL; the registry surfaces it as status
|
|
78
|
-
* "auth_required" and the operator opens it. The /oauth/callback/<id> route then
|
|
79
|
-
* drives transport.finishAuth(code).
|
|
80
|
-
*/
|
|
81
|
-
export declare class KvOAuthProvider implements OAuthClientProvider {
|
|
82
|
-
private readonly connectorId;
|
|
83
|
-
private readonly storage;
|
|
84
|
-
private readonly redirectUri;
|
|
85
|
-
private readonly refreshCoordinator?;
|
|
86
|
-
private readonly allowAuthorization;
|
|
87
|
-
/**
|
|
88
|
-
* The reset generation this provider's flow started under. Every OAuth value
|
|
89
|
-
* it writes carries this epoch, so a late write can land after a reset without
|
|
90
|
-
* becoming readable under the new generation.
|
|
91
|
-
*/
|
|
92
|
-
private capturedGeneration;
|
|
93
|
-
private refreshFlight;
|
|
94
|
-
/** Tokens this request's issuer-aware auth flow decided to refresh. */
|
|
95
|
-
private refreshBasis;
|
|
96
|
-
constructor(connectorId: string, storage: KVStorage, redirectUri: string, refreshCoordinator?: OAuthRefreshCoordinator | undefined, allowAuthorization?: boolean);
|
|
97
|
-
/**
|
|
98
|
-
* Stamp the force-reauth generation the current connect flow started under.
|
|
99
|
-
* Called by the connector once per connect, before c.connect(). The callback
|
|
100
|
-
* path captures the generation stored beside its verified state instead.
|
|
101
|
-
*/
|
|
102
|
-
captureGeneration(gen: string): void;
|
|
103
|
-
/** The generation captured for this flow, before a concurrent reset. */
|
|
104
|
-
flowGeneration(): Promise<string>;
|
|
105
|
-
/** @internal Record the refresh attempt this provider owns. */
|
|
106
|
-
captureRefreshFlight(generation: string, flight: OAuthRefreshFlight): void;
|
|
107
|
-
private failRefreshFlight;
|
|
108
|
-
/** True when another request saved a refresh result after this flow's read. */
|
|
109
|
-
refreshBasisChanged(current: OAuthTokens, generation: string): boolean;
|
|
110
|
-
/**
|
|
111
|
-
* The epoch this provider writes under. Direct unit/custom use lazily captures
|
|
112
|
-
* the current generation; connector-driven connect and callback paths stamp it
|
|
113
|
-
* explicitly before the SDK can write.
|
|
114
|
-
*/
|
|
115
|
-
private writeGeneration;
|
|
116
|
-
/**
|
|
117
|
-
* Store a value in the flow's physical epoch namespace. The pre-write check
|
|
118
|
-
* avoids needless stale residue. The namespaced key closes the remaining
|
|
119
|
-
* check-then-write race: a late old write cannot overwrite a replacement
|
|
120
|
-
* flow's value because the two writes have different physical keys.
|
|
121
|
-
*/
|
|
122
|
-
private writeValue;
|
|
123
|
-
/**
|
|
124
|
-
* Read a value only when it belongs to the active generation. Plain legacy
|
|
125
|
-
* values remain readable until the first v2 reset, so upgrades do not discard
|
|
126
|
-
* an existing grant; once a modern epoch exists, untagged residue fails
|
|
127
|
-
* closed.
|
|
128
|
-
*/
|
|
129
|
-
private readValue;
|
|
130
|
-
/**
|
|
131
|
-
* Read credentials only for the authorization server that issued them.
|
|
132
|
-
*
|
|
133
|
-
* Values written before issuer binding are bound on their first read with a
|
|
134
|
-
* validated SDK issuer, preserving an existing grant across this upgrade.
|
|
135
|
-
* A later issuer change is different: publish a new generation before
|
|
136
|
-
* returning no credentials, so every isolate drops the old registration and
|
|
137
|
-
* token set and the SDK starts authorization from scratch.
|
|
138
|
-
*/
|
|
139
|
-
private readIssuerBoundValue;
|
|
140
|
-
/** Attempt every key deletion, then report the first backend failure. */
|
|
141
|
-
private deleteAll;
|
|
142
|
-
private cleanupBacklog;
|
|
143
|
-
private rememberRetiredGeneration;
|
|
144
|
-
private valueKeysForGeneration;
|
|
145
|
-
get redirectUrl(): string;
|
|
146
|
-
get clientMetadata(): OAuthClientMetadata;
|
|
147
|
-
clientInformation(ctx?: OAuthClientInformationContext): Promise<OAuthClientInformationMixed | undefined>;
|
|
148
|
-
saveClientInformation(info: OAuthClientInformationMixed, ctx?: OAuthClientInformationContext): Promise<void>;
|
|
149
|
-
discoveryState(): Promise<OAuthDiscoveryState | undefined>;
|
|
150
|
-
saveDiscoveryState(state: OAuthDiscoveryState): Promise<void>;
|
|
151
|
-
tokens(ctx?: OAuthClientInformationContext): Promise<OAuthTokens | undefined>;
|
|
152
|
-
saveTokens(tokens: OAuthTokens, ctx?: OAuthClientInformationContext): Promise<void>;
|
|
153
|
-
/**
|
|
154
|
-
* OAuth `state`. The SDK calls this (when present) and appends the value to
|
|
155
|
-
* the authorization URL. We generate a fresh random value and persist it so
|
|
156
|
-
* the public /oauth/callback route can prove the callback belongs to a flow
|
|
157
|
-
* WE started. Without it, anyone holding a pending authorization URL could
|
|
158
|
-
* complete consent with their own account (login CSRF) — PKCE does not help,
|
|
159
|
-
* since the verifier belongs to connecta, not the attacker. Cleared in
|
|
160
|
-
* clearPending() once the flow completes.
|
|
161
|
-
*/
|
|
162
|
-
state(): Promise<string>;
|
|
163
|
-
/**
|
|
164
|
-
* Constant-time check of a callback's `state` against the stored one-shot
|
|
165
|
-
* value. Absent stored state or absent candidate → false (fail closed).
|
|
166
|
-
*/
|
|
167
|
-
verifyState(candidate: string | null): Promise<boolean>;
|
|
168
|
-
saveCodeVerifier(verifier: string): Promise<void>;
|
|
169
|
-
codeVerifier(): Promise<string>;
|
|
170
|
-
redirectToAuthorization(authorizationUrl: URL): Promise<void>;
|
|
171
|
-
/** The stored authorization URL, if a flow is pending. */
|
|
172
|
-
pendingAuthorizationUrl(): Promise<string | undefined>;
|
|
173
|
-
/** Clear one-shot flow state after the callback completes. */
|
|
174
|
-
clearPending(): Promise<void>;
|
|
175
|
-
/**
|
|
176
|
-
* Force-reauth epoch shared across isolates through storage. Old numeric
|
|
177
|
-
* generations remain valid strings for migration; new resets use unique
|
|
178
|
-
* nonces, avoiding the lost-update race of read/increment/write.
|
|
179
|
-
*/
|
|
180
|
-
generation(): Promise<string>;
|
|
181
|
-
/** True only after an operator disconnect, until an explicit authorization starts. */
|
|
182
|
-
operatorDisconnected(): Promise<boolean>;
|
|
183
|
-
/** Interpret a generation already read by a connector without another KV lookup. */
|
|
184
|
-
isOperatorDisconnectedGeneration(generation: string): boolean;
|
|
185
|
-
/** Publish a unique active epoch without a read/modify/write race. */
|
|
186
|
-
bumpGeneration(): Promise<string>;
|
|
187
|
-
/**
|
|
188
|
-
* Fence every flow that could still write, then remove all durable and
|
|
189
|
-
* one-shot authorization state. The generation is intentionally retained:
|
|
190
|
-
* it is the epoch fence that tells another isolate not to resurrect
|
|
191
|
-
* credentials it read before this reset.
|
|
192
|
-
*
|
|
193
|
-
* Once the fence is durable, attempt every deletion even if one fails. A
|
|
194
|
-
* partial backend outage should not leave unrelated secrets behind merely
|
|
195
|
-
* because an earlier key happened to be the first failed delete.
|
|
196
|
-
*/
|
|
197
|
-
resetAuthorization(operatorDisconnected?: boolean): Promise<void>;
|
|
198
|
-
invalidateCredentials(scope: "all" | "client" | "tokens" | "verifier" | "discovery"): Promise<void>;
|
|
199
|
-
}
|
|
200
|
-
export {};
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { ToolDef } from "./types.js";
|
|
2
|
-
export interface CatalogSnapshot {
|
|
3
|
-
tools: ToolDef[];
|
|
4
|
-
/** SHA-256 over the exact serialized tool array, prefixed with its size. */
|
|
5
|
-
fingerprint: string;
|
|
6
|
-
/** UTF-8 form reused by hashing, size enforcement, and chunking. */
|
|
7
|
-
serializedBytes: Uint8Array;
|
|
8
|
-
}
|
|
9
|
-
/** Fingerprint an already serialized catalog without parsing/reserializing it. */
|
|
10
|
-
export declare function fingerprintSerializedCatalog(serializedTools: string): Promise<{
|
|
11
|
-
fingerprint: string;
|
|
12
|
-
byteLength: number;
|
|
13
|
-
}>;
|
|
14
|
-
/**
|
|
15
|
-
* Capture every persisted/discovered field in one deterministic snapshot.
|
|
16
|
-
* Object key order is allowed to cause a conservative extra write; changing
|
|
17
|
-
* any serialized field must change the digest.
|
|
18
|
-
*/
|
|
19
|
-
export declare function snapshotCatalog(tools: ToolDef[]): Promise<CatalogSnapshot>;
|
package/dist/catalog-limits.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/** Complete-catalog ceiling shared by dynamically listed connector catalogs. */
|
|
2
|
-
export declare const MAX_CATALOG_TOOLS = 100000;
|
|
3
|
-
/**
|
|
4
|
-
* Large enough to cross a single Workers KV value boundary while keeping the
|
|
5
|
-
* serialized form at one quarter of a 128 MiB Worker heap.
|
|
6
|
-
*/
|
|
7
|
-
export declare const MAX_SERIALIZED_CATALOG_BYTES: number;
|
|
8
|
-
/** Persisted values stay comfortably below platform per-value limits. */
|
|
9
|
-
export declare const MAX_CATALOG_CHUNK_BYTES: number;
|
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
import type { CallErrorDetails } from "./errors.js";
|
|
2
|
-
import type { ConnectorOperationOptions, RegistryView } from "./registry.js";
|
|
3
|
-
import type { DeferredWork } from "./connector-scope.js";
|
|
4
|
-
import type { Connector, ToolDef } from "./types.js";
|
|
5
|
-
export declare const DEFAULT_SEARCH_LIMIT = 8;
|
|
6
|
-
export declare const MAX_SEARCH_LIMIT = 100;
|
|
7
|
-
export declare const MAX_DESCRIBE_ADDRESSES = 100;
|
|
8
|
-
export declare const MAX_DISCOVERY_RESULT_BYTES = 256000;
|
|
9
|
-
/**
|
|
10
|
-
* The discovery route a routing failure should send a caller back through. Same
|
|
11
|
-
* catalog logic serves both the top-level `search_tools` path and the
|
|
12
|
-
* in-program `connecta.search` path, so callers pass the route they own.
|
|
13
|
-
*/
|
|
14
|
-
export type SearchRoute = "search_tools" | "connecta.search";
|
|
15
|
-
export declare class DiscoveryPolicyError extends Error {
|
|
16
|
-
readonly code: "invalid_args" | "result_too_large";
|
|
17
|
-
constructor(code: "invalid_args" | "result_too_large", message: string);
|
|
18
|
-
}
|
|
19
|
-
/** Serialize once and count the exact bytes the MCP adapter would emit. */
|
|
20
|
-
export declare function boundedDiscoveryText(value: unknown, hint: string): string;
|
|
21
|
-
export interface CatalogSearchArgs {
|
|
22
|
-
query?: string;
|
|
23
|
-
connector?: string;
|
|
24
|
-
/**
|
|
25
|
-
* Result classification only; never changes which tools exist or what may
|
|
26
|
-
* execute. Omitted and "all" preserve the complete configured catalog.
|
|
27
|
-
*/
|
|
28
|
-
safety?: "readOnly" | "approvalRequired" | "all";
|
|
29
|
-
limit?: number;
|
|
30
|
-
offset?: number;
|
|
31
|
-
fullDescriptions?: boolean;
|
|
32
|
-
includeSchemas?: "compact" | "json";
|
|
33
|
-
/** Code-mode helper metadata; never exposed by the public search_tools schema. */
|
|
34
|
-
includeSchemaKeys?: boolean;
|
|
35
|
-
}
|
|
36
|
-
export interface CatalogDescribeArgs {
|
|
37
|
-
address?: unknown;
|
|
38
|
-
addresses?: unknown;
|
|
39
|
-
format?: "compact" | "json";
|
|
40
|
-
fullDescriptions?: boolean;
|
|
41
|
-
}
|
|
42
|
-
interface CatalogSearchEntry {
|
|
43
|
-
connector: Connector;
|
|
44
|
-
guide?: string;
|
|
45
|
-
guideSummary?: string;
|
|
46
|
-
tool: {
|
|
47
|
-
name: string;
|
|
48
|
-
address: string;
|
|
49
|
-
description?: string;
|
|
50
|
-
inputSchema?: unknown;
|
|
51
|
-
outputSchema?: unknown;
|
|
52
|
-
outputSchemaSource?: "observed";
|
|
53
|
-
inputSchemaTruncated?: true;
|
|
54
|
-
outputSchemaTruncated?: true;
|
|
55
|
-
inputKeys?: string[];
|
|
56
|
-
requiredInputKeys?: string[];
|
|
57
|
-
outputKeys?: string[];
|
|
58
|
-
annotations?: ToolDef["annotations"];
|
|
59
|
-
guideRequired?: true;
|
|
60
|
-
guideRequiredReasons?: GuideRequiredReason[];
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
type GuideRequiredReason = "connector_required" | "approval_required" | "schema_truncated";
|
|
64
|
-
/**
|
|
65
|
-
* The classified-failure subset a scoped search may echo: enough to tell a
|
|
66
|
-
* transient outage from one an operator must clear, and nothing more. Kept as
|
|
67
|
-
* its own type rather than `CallErrorDetails` so widening the call-path
|
|
68
|
-
* classifier cannot widen this discovery-surface field by accident.
|
|
69
|
-
*/
|
|
70
|
-
interface CatalogFailureDetail {
|
|
71
|
-
code: string;
|
|
72
|
-
message: string;
|
|
73
|
-
retryable: boolean;
|
|
74
|
-
retryAfterMs?: number;
|
|
75
|
-
}
|
|
76
|
-
interface CatalogDescriptionFailureDetail extends CatalogFailureDetail {
|
|
77
|
-
nextAction?: NonNullable<CallErrorDetails["nextAction"]>;
|
|
78
|
-
/** Nearby canonical addresses, ranked deterministically by tool name. */
|
|
79
|
-
suggestions?: string[];
|
|
80
|
-
}
|
|
81
|
-
export interface CatalogSearchPage {
|
|
82
|
-
entries: CatalogSearchEntry[];
|
|
83
|
-
total: number;
|
|
84
|
-
offset: number;
|
|
85
|
-
limit: number;
|
|
86
|
-
hasMore: boolean;
|
|
87
|
-
nextOffset?: number;
|
|
88
|
-
matchMode?: "partial";
|
|
89
|
-
queryAnalysis?: {
|
|
90
|
-
representedTerms: string[];
|
|
91
|
-
otherResultTerms: string[];
|
|
92
|
-
unmatchedTerms: string[];
|
|
93
|
-
truncated?: true;
|
|
94
|
-
connectorScope?: string;
|
|
95
|
-
unknownConnector?: true;
|
|
96
|
-
unavailableConnectorCount?: number;
|
|
97
|
-
/** Bounded typed failure for an explicitly scoped unavailable catalog. */
|
|
98
|
-
catalogError?: CatalogFailureDetail;
|
|
99
|
-
guide?: string;
|
|
100
|
-
guideSummary?: string;
|
|
101
|
-
guideRequired?: true;
|
|
102
|
-
guideRequiredReasons?: GuideRequiredReason[];
|
|
103
|
-
guidance?: string;
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
export interface CatalogDescription {
|
|
107
|
-
address: string;
|
|
108
|
-
name?: string;
|
|
109
|
-
description?: string;
|
|
110
|
-
guide?: string;
|
|
111
|
-
guideSummary?: string;
|
|
112
|
-
guideRequired?: true;
|
|
113
|
-
guideRequiredReasons?: GuideRequiredReason[];
|
|
114
|
-
inputSchema?: unknown;
|
|
115
|
-
outputSchema?: unknown;
|
|
116
|
-
outputSchemaSource?: "observed";
|
|
117
|
-
inputSchemaTruncated?: true;
|
|
118
|
-
outputSchemaTruncated?: true;
|
|
119
|
-
annotations?: ToolDef["annotations"];
|
|
120
|
-
error?: string;
|
|
121
|
-
errorDetails?: CatalogDescriptionFailureDetail;
|
|
122
|
-
}
|
|
123
|
-
export interface ResolvedCatalogTool {
|
|
124
|
-
connector: Connector;
|
|
125
|
-
toolName: string;
|
|
126
|
-
definition: ToolDef;
|
|
127
|
-
}
|
|
128
|
-
export type CatalogResolution = {
|
|
129
|
-
ok: true;
|
|
130
|
-
resolved: ResolvedCatalogTool;
|
|
131
|
-
catalogMs: number;
|
|
132
|
-
} | {
|
|
133
|
-
ok: false;
|
|
134
|
-
error: CallErrorDetails;
|
|
135
|
-
catalogMs: number;
|
|
136
|
-
connector?: Connector;
|
|
137
|
-
toolName?: string;
|
|
138
|
-
cause?: unknown;
|
|
139
|
-
};
|
|
140
|
-
/**
|
|
141
|
-
* Request-local catalog operations shared by MCP meta-tools and code mode.
|
|
142
|
-
* Successful catalogs may be reused inside this request; failures are not
|
|
143
|
-
* retained, and the service itself never escapes its request adapter.
|
|
144
|
-
*/
|
|
145
|
-
export declare class CatalogService {
|
|
146
|
-
private readonly registry;
|
|
147
|
-
readonly baseUrl: string;
|
|
148
|
-
readonly requestScope: object;
|
|
149
|
-
private readonly probeTimeoutMs;
|
|
150
|
-
private readonly concurrency;
|
|
151
|
-
private readonly searchRoute;
|
|
152
|
-
private readonly readOptions;
|
|
153
|
-
private readonly loaded;
|
|
154
|
-
private readonly loading;
|
|
155
|
-
constructor(registry: RegistryView, baseUrl: string, options?: {
|
|
156
|
-
requestScope?: object | undefined;
|
|
157
|
-
probeTimeoutMs?: number | undefined;
|
|
158
|
-
concurrency?: number | undefined;
|
|
159
|
-
/** The discovery route recovery records name. Default `search_tools`. */
|
|
160
|
-
searchRoute?: SearchRoute | undefined;
|
|
161
|
-
/** Runtime-owned tail for stale-while-revalidate catalog reads. */
|
|
162
|
-
defer?: DeferredWork | undefined;
|
|
163
|
-
});
|
|
164
|
-
/**
|
|
165
|
-
* Send a caller back to discovery through the surface it can actually reach.
|
|
166
|
-
* Both variants carry the same scoping arguments because `connecta.search`
|
|
167
|
-
* takes the same ones `search_tools` does; only the key naming the callable
|
|
168
|
-
* differs, the way the ambiguous-alias record already names a function.
|
|
169
|
-
*
|
|
170
|
-
* Not private: `InvocationService` builds the same class of record when a
|
|
171
|
-
* call fails schema validation, and it is this catalog's route that decides
|
|
172
|
-
* which key that record carries. Duplicating the branch there would let the
|
|
173
|
-
* two drift.
|
|
174
|
-
*/
|
|
175
|
-
searchRecovery(args: {
|
|
176
|
-
query: string;
|
|
177
|
-
connector?: string;
|
|
178
|
-
}, purpose: string): NonNullable<CallErrorDetails["nextAction"]>;
|
|
179
|
-
loadConnector(id: string, callOptions?: ConnectorOperationOptions): Promise<ToolDef[]>;
|
|
180
|
-
private loadForDiscovery;
|
|
181
|
-
private outputSchema;
|
|
182
|
-
private unknownAddressFailure;
|
|
183
|
-
private catalogLoadFailure;
|
|
184
|
-
private unknownToolFailure;
|
|
185
|
-
resolveTool(address: string, callOptions?: ConnectorOperationOptions): Promise<CatalogResolution>;
|
|
186
|
-
search(args: CatalogSearchArgs): Promise<CatalogSearchPage>;
|
|
187
|
-
describe(args: CatalogDescribeArgs): Promise<CatalogDescription[]>;
|
|
188
|
-
}
|
|
189
|
-
export declare function groupedSearchResult(page: CatalogSearchPage): {
|
|
190
|
-
queryAnalysis?: {
|
|
191
|
-
representedTerms: string[];
|
|
192
|
-
otherResultTerms: string[];
|
|
193
|
-
unmatchedTerms: string[];
|
|
194
|
-
truncated?: true;
|
|
195
|
-
connectorScope?: string;
|
|
196
|
-
unknownConnector?: true;
|
|
197
|
-
unavailableConnectorCount?: number;
|
|
198
|
-
/** Bounded typed failure for an explicitly scoped unavailable catalog. */
|
|
199
|
-
catalogError?: CatalogFailureDetail;
|
|
200
|
-
guide?: string;
|
|
201
|
-
guideSummary?: string;
|
|
202
|
-
guideRequired?: true;
|
|
203
|
-
guideRequiredReasons?: GuideRequiredReason[];
|
|
204
|
-
guidance?: string;
|
|
205
|
-
};
|
|
206
|
-
matchMode?: "partial";
|
|
207
|
-
nextOffset?: number;
|
|
208
|
-
total: number;
|
|
209
|
-
offset: number;
|
|
210
|
-
limit: number;
|
|
211
|
-
hasMore: boolean;
|
|
212
|
-
connectors: {
|
|
213
|
-
id: string;
|
|
214
|
-
title?: string;
|
|
215
|
-
guide?: string;
|
|
216
|
-
guideSummary?: string;
|
|
217
|
-
tools: CatalogSearchEntry["tool"][];
|
|
218
|
-
}[];
|
|
219
|
-
};
|
|
220
|
-
export declare function flatSearchResult(page: CatalogSearchPage): {
|
|
221
|
-
queryAnalysis?: {
|
|
222
|
-
representedTerms: string[];
|
|
223
|
-
otherResultTerms: string[];
|
|
224
|
-
unmatchedTerms: string[];
|
|
225
|
-
truncated?: true;
|
|
226
|
-
connectorScope?: string;
|
|
227
|
-
unknownConnector?: true;
|
|
228
|
-
unavailableConnectorCount?: number;
|
|
229
|
-
/** Bounded typed failure for an explicitly scoped unavailable catalog. */
|
|
230
|
-
catalogError?: CatalogFailureDetail;
|
|
231
|
-
guide?: string;
|
|
232
|
-
guideSummary?: string;
|
|
233
|
-
guideRequired?: true;
|
|
234
|
-
guideRequiredReasons?: GuideRequiredReason[];
|
|
235
|
-
guidance?: string;
|
|
236
|
-
};
|
|
237
|
-
matchMode?: "partial";
|
|
238
|
-
nextOffset?: number;
|
|
239
|
-
total: number;
|
|
240
|
-
offset: number;
|
|
241
|
-
limit: number;
|
|
242
|
-
hasMore: boolean;
|
|
243
|
-
tools: {
|
|
244
|
-
guideSummary?: string;
|
|
245
|
-
guide?: string;
|
|
246
|
-
connectorTitle?: string;
|
|
247
|
-
name: string;
|
|
248
|
-
address: string;
|
|
249
|
-
description?: string;
|
|
250
|
-
inputSchema?: unknown;
|
|
251
|
-
outputSchema?: unknown;
|
|
252
|
-
outputSchemaSource?: "observed";
|
|
253
|
-
inputSchemaTruncated?: true;
|
|
254
|
-
outputSchemaTruncated?: true;
|
|
255
|
-
inputKeys?: string[];
|
|
256
|
-
requiredInputKeys?: string[];
|
|
257
|
-
outputKeys?: string[];
|
|
258
|
-
annotations?: ToolDef["annotations"];
|
|
259
|
-
guideRequired?: true;
|
|
260
|
-
guideRequiredReasons?: GuideRequiredReason[];
|
|
261
|
-
}[];
|
|
262
|
-
};
|
|
263
|
-
export {};
|
package/dist/catalog.d.ts
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import type { JsonSchema, ToolDef } from "./types.js";
|
|
2
|
-
export declare const MAX_COMPACT_DISCOVERY_SCHEMA_BYTES = 1024;
|
|
3
|
-
export declare function summarizeDescription(text: string | undefined, full: boolean): string | undefined;
|
|
4
|
-
export declare function summarizeDiscoveryDescription(text: string | undefined, full: boolean): string | undefined;
|
|
5
|
-
/** Distinct normalized terms in query order, shared by ranking and feedback. */
|
|
6
|
-
export declare function lexicalQueryTerms(query: string): string[];
|
|
7
|
-
/**
|
|
8
|
-
* Remove conversational framing before the all-term/partial decision. If
|
|
9
|
-
* every term is framing, retain the original query rather than turning a
|
|
10
|
-
* search into an unfiltered catalog browse.
|
|
11
|
-
*/
|
|
12
|
-
export declare function lexicalSearchQuery(query: string): string;
|
|
13
|
-
export type LexicalMatchMode = "all" | "partial";
|
|
14
|
-
export interface RankedTool {
|
|
15
|
-
tool: ToolDef;
|
|
16
|
-
score: number;
|
|
17
|
-
order: number;
|
|
18
|
-
exactName: boolean;
|
|
19
|
-
matchedTermCount: number;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Whether one query term matches a whole token of arbitrary text, under the
|
|
23
|
-
* same inflection rules the tool index uses.
|
|
24
|
-
*
|
|
25
|
-
* Connector identity — an `id` or a `title` — is deliberately not a document in
|
|
26
|
-
* that index: making it one would move ranking for every query that already
|
|
27
|
-
* matches tools. This lets a caller ask the index's question of a string that
|
|
28
|
-
* never became a document, which is what the no-match analysis needs to tell
|
|
29
|
-
* "nothing like this exists here" from "that word is a connector".
|
|
30
|
-
*/
|
|
31
|
-
export declare function matchesLexicalTerm(text: string, term: string): boolean;
|
|
32
|
-
export interface LexicalCorpusStatistics {
|
|
33
|
-
documentCount: number;
|
|
34
|
-
documentFrequency: ReadonlyMap<string, number>;
|
|
35
|
-
nameMatches: ReadonlyMap<string, ReadonlySet<ToolDef>>;
|
|
36
|
-
descriptionMatches: ReadonlyMap<string, ReadonlySet<ToolDef>>;
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Compute query-specific document frequencies across every available catalog.
|
|
40
|
-
* The caller does this once per search and shares the result with each
|
|
41
|
-
* connector rank, so ubiquitous words contribute less than discriminative
|
|
42
|
-
* ones without making any action word a stopword.
|
|
43
|
-
*/
|
|
44
|
-
export declare function lexicalCorpusStatistics(toolSets: ToolDef[][], query: string): LexicalCorpusStatistics;
|
|
45
|
-
/**
|
|
46
|
-
* Rank a connector's tools while caching its normalized plain-data index.
|
|
47
|
-
* `exactNameQuery` may retain framing removed from the scoring query: those
|
|
48
|
-
* words are weak term evidence, but remain part of a real tool-name phrase.
|
|
49
|
-
*/
|
|
50
|
-
export declare function rankTools(tools: ToolDef[], query: string, mode?: LexicalMatchMode, statistics?: LexicalCorpusStatistics, exactNameQuery?: string): RankedTool[];
|
|
51
|
-
/** Render and cache a compact TypeScript-like representation of JSON Schema. */
|
|
52
|
-
export declare function compactSchema(schema: JsonSchema): string;
|
|
53
|
-
/** Describe allows 8 KiB for property prose, with the same work cap as search. */
|
|
54
|
-
export declare function compactDescriptionSchema(schema: JsonSchema): CompactDiscoverySchema;
|
|
55
|
-
export interface CompactDiscoverySchema {
|
|
56
|
-
text: string;
|
|
57
|
-
truncated: boolean;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Render the schema shape carried by search results.
|
|
61
|
-
*
|
|
62
|
-
* Search is a routing step, so repeated property prose does not earn its
|
|
63
|
-
* context cost there. Required inputs render first, and the result has a hard
|
|
64
|
-
* UTF-8 budget; exact JSON and the prose-rich compact rendering remain
|
|
65
|
-
* available through the existing full retrieval paths.
|
|
66
|
-
*/
|
|
67
|
-
export declare function compactDiscoverySchema(schema: JsonSchema): CompactDiscoverySchema;
|
|
68
|
-
/** The property and required names a schema resolves to, or undefined. */
|
|
69
|
-
export interface SchemaObjectKeys {
|
|
70
|
-
properties: string[];
|
|
71
|
-
required: string[];
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Walk a schema the way renderSchema does — composing `allOf` and resolving
|
|
75
|
-
* `$ref` against the root's `$defs`/`definitions` — and collect the top-level
|
|
76
|
-
* property names it would render. A shallow `Object.keys(schema.properties)`
|
|
77
|
-
* disagrees with the rendered compact schema for exactly the shapes real
|
|
78
|
-
* connectors emit (a top-level `$ref` to a `$defs` entry, or the OpenAPI
|
|
79
|
-
* "extend this base" `allOf`), which is worse than no metadata at all: it
|
|
80
|
-
* reports an empty field list for a tool that plainly has fields.
|
|
81
|
-
*
|
|
82
|
-
* Returns undefined when the schema is not an object shape at all — a union,
|
|
83
|
-
* array, enum, or unresolvable `$ref`. Absent metadata tells a caller to read
|
|
84
|
-
* the rendered schema instead; an empty array would claim the tool takes no
|
|
85
|
-
* fields.
|
|
86
|
-
*/
|
|
87
|
-
export declare function schemaObjectKeys(schema: JsonSchema | undefined): SchemaObjectKeys | undefined;
|
package/dist/concurrency.d.ts
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
export declare function resolveDiscoveryConcurrency(value: number | undefined): number;
|
|
2
|
-
/** Run `fn` over `items` with at most `limit` operations in flight. */
|
|
3
|
-
export declare function mapSettledWithConcurrency<T, R>(items: readonly T[], limit: number, fn: (item: T, index: number) => Promise<R>): Promise<PromiseSettledResult<R>[]>;
|