@zackbart/connecta 0.7.7 → 0.7.9
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 +88 -0
- package/dist/activity.d.ts +1 -1
- package/dist/activity.d.ts.map +1 -1
- package/dist/activity.js.map +1 -1
- package/dist/call-admission.d.ts +81 -0
- package/dist/call-admission.d.ts.map +1 -0
- package/dist/call-admission.js +339 -0
- package/dist/call-admission.js.map +1 -0
- package/dist/catalog.d.ts +5 -3
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +13 -4
- package/dist/catalog.js.map +1 -1
- package/dist/connectors/api.d.ts +3 -1
- package/dist/connectors/api.d.ts.map +1 -1
- package/dist/connectors/api.js +1 -0
- package/dist/connectors/api.js.map +1 -1
- package/dist/connectors/remote-mcp.d.ts +3 -1
- package/dist/connectors/remote-mcp.d.ts.map +1 -1
- package/dist/connectors/remote-mcp.js +1 -0
- package/dist/connectors/remote-mcp.js.map +1 -1
- package/dist/execute.d.ts.map +1 -1
- package/dist/execute.js +72 -30
- package/dist/execute.js.map +1 -1
- package/dist/index.d.ts +9 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/meta-tools.d.ts +7 -4
- package/dist/meta-tools.d.ts.map +1 -1
- package/dist/meta-tools.js +212 -54
- package/dist/meta-tools.js.map +1 -1
- package/dist/registry.d.ts +37 -0
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +45 -2
- package/dist/registry.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +5 -0
- package/dist/server.js.map +1 -1
- package/dist/types.d.ts +55 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/ui.d.ts.map +1 -1
- package/dist/ui.js +8 -4
- package/dist/ui.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/src/activity.ts +5 -1
- package/src/call-admission.ts +519 -0
- package/src/catalog.ts +24 -4
- package/src/connectors/api.ts +4 -0
- package/src/connectors/remote-mcp.ts +4 -0
- package/src/execute.ts +83 -35
- package/src/index.ts +14 -1
- package/src/meta-tools.ts +246 -70
- package/src/registry.ts +91 -1
- package/src/server.ts +5 -0
- package/src/types.ts +61 -0
- package/src/ui.ts +8 -4
- package/src/version.ts +1 -1
package/src/execute.ts
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
truncateExecuteText,
|
|
17
17
|
} from "./executor-result.js";
|
|
18
18
|
import { classifyCallError, ConnectorCallError } from "./errors.js";
|
|
19
|
+
import { isCallAdmissionError } from "./call-admission.js";
|
|
19
20
|
import {
|
|
20
21
|
ExecutorAdmissionError,
|
|
21
22
|
isAdmittingExecutor,
|
|
@@ -192,27 +193,37 @@ export async function buildSandboxProviders(
|
|
|
192
193
|
const controller = new AbortController();
|
|
193
194
|
const cancel = () => controller.abort(limits.signal?.reason);
|
|
194
195
|
limits.signal?.addEventListener("abort", cancel, { once: true });
|
|
196
|
+
if (limits.signal?.aborted) cancel();
|
|
195
197
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
196
|
-
let
|
|
197
|
-
const cancelled = new Promise<never>((_, reject) => {
|
|
198
|
-
rejectCancelled = reject;
|
|
199
|
-
});
|
|
200
|
-
const onAbort = () => {
|
|
201
|
-
rejectCancelled(
|
|
202
|
-
controller.signal.reason instanceof Error
|
|
203
|
-
? controller.signal.reason
|
|
204
|
-
: new Error("execute_code host call cancelled"),
|
|
205
|
-
);
|
|
206
|
-
};
|
|
207
|
-
controller.signal.addEventListener("abort", onAbort, { once: true });
|
|
208
|
-
const ctx = registry.contextFor(
|
|
209
|
-
resolved.connector.id,
|
|
210
|
-
baseUrl,
|
|
211
|
-
requestScope,
|
|
212
|
-
{ signal: controller.signal, timeoutMs: hostCallTimeoutMs },
|
|
213
|
-
);
|
|
198
|
+
let onAbort: (() => void) | undefined;
|
|
214
199
|
const started = Date.now();
|
|
200
|
+
let permit: Awaited<ReturnType<RegistryView["admitCall"]>> | undefined;
|
|
215
201
|
try {
|
|
202
|
+
permit = await registry.admitCall(resolved.connector.id, {
|
|
203
|
+
toolName: resolved.toolName,
|
|
204
|
+
args: args ?? {},
|
|
205
|
+
signal: controller.signal,
|
|
206
|
+
});
|
|
207
|
+
let rejectCancelled!: (reason: Error) => void;
|
|
208
|
+
const cancelled = new Promise<never>((_, reject) => {
|
|
209
|
+
rejectCancelled = reject;
|
|
210
|
+
});
|
|
211
|
+
onAbort = () => {
|
|
212
|
+
rejectCancelled(
|
|
213
|
+
controller.signal.reason instanceof Error
|
|
214
|
+
? controller.signal.reason
|
|
215
|
+
: new Error("execute_code host call cancelled"),
|
|
216
|
+
);
|
|
217
|
+
};
|
|
218
|
+
controller.signal.addEventListener("abort", onAbort, { once: true });
|
|
219
|
+
if (controller.signal.aborted) onAbort();
|
|
220
|
+
if (controller.signal.aborted) await cancelled;
|
|
221
|
+
const ctx = registry.contextFor(
|
|
222
|
+
resolved.connector.id,
|
|
223
|
+
baseUrl,
|
|
224
|
+
requestScope,
|
|
225
|
+
{ signal: controller.signal, timeoutMs: hostCallTimeoutMs },
|
|
226
|
+
);
|
|
216
227
|
timer = setTimeout(() => {
|
|
217
228
|
controller.abort(
|
|
218
229
|
new ConnectorCallError(
|
|
@@ -242,14 +253,34 @@ export async function buildSandboxProviders(
|
|
|
242
253
|
});
|
|
243
254
|
return value;
|
|
244
255
|
} catch (err) {
|
|
245
|
-
|
|
246
|
-
|
|
256
|
+
const callerCancelled =
|
|
257
|
+
limits.signal?.aborted === true ||
|
|
258
|
+
(isCallAdmissionError(err) && err.admissionKind === "cancelled");
|
|
259
|
+
if (!callerCancelled && !isCallAdmissionError(err)) {
|
|
260
|
+
registry.recordFailure(
|
|
261
|
+
resolved.connector.id,
|
|
262
|
+
Date.now() - started,
|
|
263
|
+
err,
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
const details = callerCancelled
|
|
267
|
+
? {
|
|
268
|
+
code: "cancelled",
|
|
269
|
+
message: "Tool call was cancelled by the caller.",
|
|
270
|
+
retryable: false,
|
|
271
|
+
}
|
|
272
|
+
: classifyCallError(err);
|
|
247
273
|
recordToolActivity(activity, {
|
|
248
274
|
connectorId: resolved.connector.id,
|
|
249
275
|
toolName: resolved.toolName,
|
|
250
276
|
address: `${resolved.connector.id}.${resolved.toolName}`,
|
|
251
277
|
source: "execute_code",
|
|
252
|
-
outcome:
|
|
278
|
+
outcome:
|
|
279
|
+
details.code === "timeout"
|
|
280
|
+
? "timeout"
|
|
281
|
+
: details.code === "cancelled"
|
|
282
|
+
? "cancelled"
|
|
283
|
+
: "error",
|
|
253
284
|
durationMs: Date.now() - started,
|
|
254
285
|
attempts: 1,
|
|
255
286
|
errorCode: details.code,
|
|
@@ -257,8 +288,9 @@ export async function buildSandboxProviders(
|
|
|
257
288
|
throw err;
|
|
258
289
|
} finally {
|
|
259
290
|
if (timer) clearTimeout(timer);
|
|
260
|
-
controller.signal.removeEventListener("abort", onAbort);
|
|
291
|
+
if (onAbort) controller.signal.removeEventListener("abort", onAbort);
|
|
261
292
|
limits.signal?.removeEventListener("abort", cancel);
|
|
293
|
+
permit?.release();
|
|
262
294
|
}
|
|
263
295
|
};
|
|
264
296
|
for (let i = 0; i < connectors.length; i++) {
|
|
@@ -369,20 +401,33 @@ export async function buildSandboxProviders(
|
|
|
369
401
|
score: number;
|
|
370
402
|
order: number;
|
|
371
403
|
}> = [];
|
|
372
|
-
let
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
404
|
+
let matchMode: "all" | "partial" = "all";
|
|
405
|
+
const collectMatches = (mode: "all" | "partial") => {
|
|
406
|
+
matches.length = 0;
|
|
407
|
+
let orderBase = 0;
|
|
408
|
+
for (const connector of connectors) {
|
|
409
|
+
if (args.connector && connector.id !== args.connector) continue;
|
|
410
|
+
const tools = catalogs.get(connector.id);
|
|
411
|
+
if (!tools) continue;
|
|
412
|
+
for (const ranked of rankTools(
|
|
413
|
+
tools,
|
|
414
|
+
args.query ?? "",
|
|
415
|
+
mode,
|
|
416
|
+
)) {
|
|
417
|
+
matches.push({
|
|
418
|
+
connector: connector.id,
|
|
419
|
+
tool: ranked.tool,
|
|
420
|
+
score: ranked.score,
|
|
421
|
+
order: orderBase + ranked.order,
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
orderBase += tools.length;
|
|
384
425
|
}
|
|
385
|
-
|
|
426
|
+
};
|
|
427
|
+
collectMatches("all");
|
|
428
|
+
if ((args.query ?? "").trim() && matches.length === 0) {
|
|
429
|
+
matchMode = "partial";
|
|
430
|
+
collectMatches(matchMode);
|
|
386
431
|
}
|
|
387
432
|
matches.sort((a, b) => b.score - a.score || a.order - b.order);
|
|
388
433
|
const offset = Math.max(0, Math.trunc(args.offset ?? 0));
|
|
@@ -428,6 +473,9 @@ export async function buildSandboxProviders(
|
|
|
428
473
|
limit,
|
|
429
474
|
hasMore: nextOffset !== undefined,
|
|
430
475
|
...(nextOffset !== undefined ? { nextOffset } : {}),
|
|
476
|
+
...(matchMode === "partial" && matches.length > 0
|
|
477
|
+
? { matchMode }
|
|
478
|
+
: {}),
|
|
431
479
|
};
|
|
432
480
|
assertDiscoveryResultSize(
|
|
433
481
|
result,
|
package/src/index.ts
CHANGED
|
@@ -94,7 +94,7 @@ export interface ConnectaDiscoveryConfig {
|
|
|
94
94
|
probeTimeoutMs?: number;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
/** Deployment-wide call deadlines and inline-result paging
|
|
97
|
+
/** Deployment-wide call deadlines and inline-result paging thresholds. */
|
|
98
98
|
export interface ConnectaCallsConfig {
|
|
99
99
|
/**
|
|
100
100
|
* Deadline (ms) for `call_tool`/`batch_call` calls that pass no `timeoutMs`.
|
|
@@ -111,6 +111,13 @@ export interface ConnectaCallsConfig {
|
|
|
111
111
|
* 50_000. Connectors may override it individually.
|
|
112
112
|
*/
|
|
113
113
|
maxResultBytes?: number;
|
|
114
|
+
/**
|
|
115
|
+
* Max serialized `batch_call` envelope size (bytes) before the full batch is
|
|
116
|
+
* stashed for `get_result` and only an ordered outcome summary is returned
|
|
117
|
+
* inline. Must be a finite whole number >= 1; invalid values warn and fall
|
|
118
|
+
* back to 100_000. This cap is independent of per-connector child caps.
|
|
119
|
+
*/
|
|
120
|
+
maxBatchResultBytes?: number;
|
|
114
121
|
}
|
|
115
122
|
|
|
116
123
|
export interface AdmissionPoolConfig {
|
|
@@ -544,6 +551,7 @@ export function createConnecta(config: ConnectaConfig): Connecta {
|
|
|
544
551
|
persistToolCatalog: config.discovery?.persistCatalog,
|
|
545
552
|
toolCatalogStaleSeconds: config.discovery?.staleCatalogSeconds,
|
|
546
553
|
maxResultBytes: config.calls?.maxResultBytes,
|
|
554
|
+
maxBatchResultBytes: config.calls?.maxBatchResultBytes,
|
|
547
555
|
credentialHealth: config.credentials?.health,
|
|
548
556
|
});
|
|
549
557
|
// Throws on every structural mistake it can see (see resolveToolkits): a
|
|
@@ -640,6 +648,7 @@ export function createConnecta(config: ConnectaConfig): Connecta {
|
|
|
640
648
|
closePromise ??= Promise.resolve().then(async () => {
|
|
641
649
|
requestAdmission.close();
|
|
642
650
|
codeAdmission?.close();
|
|
651
|
+
registry.closeCallAdmission();
|
|
643
652
|
await config.executor?.close?.();
|
|
644
653
|
});
|
|
645
654
|
await closePromise;
|
|
@@ -690,6 +699,10 @@ export type {
|
|
|
690
699
|
export type { ApiOptions, ApiTool } from "./connectors/api.js";
|
|
691
700
|
export type {
|
|
692
701
|
Connector,
|
|
702
|
+
ConnectorCallAdmissionInput,
|
|
703
|
+
ConnectorCallAdmissionPolicy,
|
|
704
|
+
ConnectorCallAdmissionRule,
|
|
705
|
+
ConnectorRollingWindowBudget,
|
|
693
706
|
ConnectaBranding,
|
|
694
707
|
ConnectorCredentialAccess,
|
|
695
708
|
ConnectorCredentialConfig,
|