@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/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,94 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this package are documented here.
|
|
4
4
|
|
|
5
|
+
## 0.7.9 — 2026-07-28
|
|
6
|
+
|
|
7
|
+
0.7.9 adds opt-in, connector-scoped admission for downstream tool calls. Direct
|
|
8
|
+
calls, batch children, and code-mode host calls to the same connector now share
|
|
9
|
+
one per-runtime limiter, including through toolkit-scoped views. Connectors
|
|
10
|
+
without a `callAdmission` policy behave as before. Dependencies, storage
|
|
11
|
+
formats, and package entrypoints are unchanged.
|
|
12
|
+
|
|
13
|
+
The policy is exact within one Node process or Worker isolate. Concurrency
|
|
14
|
+
limits fully contain one request's fan-out; rolling budgets remain best-effort
|
|
15
|
+
across multiple isolates, replicas, or restarts. This release deliberately
|
|
16
|
+
does not add a distributed coordinator.
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- **Connector-scoped downstream admission** (issue #138, PR #143).
|
|
21
|
+
`api()`, `remoteMcp()`, and custom connectors accept a plural-ready
|
|
22
|
+
`callAdmission.rules` policy. The single rule supported today can bound
|
|
23
|
+
concurrency, queue size and wait, and rolling-window calls, optionally
|
|
24
|
+
partitioned by a bounded operator-derived key.
|
|
25
|
+
- **Payload-free admission telemetry.** `/health` reports connector aggregates
|
|
26
|
+
for live partitions, active and queued calls, admission outcomes, and queue
|
|
27
|
+
waits without exposing partition keys, arguments, or results.
|
|
28
|
+
- **Explicit cancelled Activity outcomes.** Caller cancellation is represented
|
|
29
|
+
separately from provider errors and timeouts in the public Activity event
|
|
30
|
+
union, the operator UI, and the Worker D1 example.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- **Retries reacquire admission per attempt.** Backoff does not retain a
|
|
35
|
+
concurrency permit, and each actual retry consumes a fresh rolling-budget
|
|
36
|
+
entry. Short proactive `rate_limited` windows continue to use the existing
|
|
37
|
+
safe retry contract.
|
|
38
|
+
- **Queue and connector deadlines are separate.** `queueTimeoutMs` bounds only
|
|
39
|
+
permit wait; the per-attempt tool deadline begins after admission.
|
|
40
|
+
`diagnostics: true` reports the phases separately as `admissionMs` and
|
|
41
|
+
`connectorMs`.
|
|
42
|
+
|
|
43
|
+
### Fixed
|
|
44
|
+
|
|
45
|
+
- **Caller cancellation no longer retries an abandoned attempt or degrades
|
|
46
|
+
connector health.** A call already cancelled avoids connector dispatch.
|
|
47
|
+
Queued cancellation still releases its place without spending a
|
|
48
|
+
rolling-budget entry, while active cancellation releases its permit and
|
|
49
|
+
records a non-retryable `cancelled` result.
|
|
50
|
+
|
|
51
|
+
## 0.7.8 — 2026-07-28
|
|
52
|
+
|
|
53
|
+
0.7.8 makes dependency-free tool discovery recover from natural-language
|
|
54
|
+
queries that contain more related terms than one catalog entry covers, and
|
|
55
|
+
closes the aggregate result-size gap in `batch_call`. Small batches, exact and
|
|
56
|
+
all-term search ranking, empty-query browsing, dependencies, storage formats,
|
|
57
|
+
and package entrypoints are unchanged.
|
|
58
|
+
|
|
59
|
+
Existing deployments gain an independent 100,000-byte final batch-envelope
|
|
60
|
+
boundary. Set `calls.maxBatchResultBytes` to another whole positive byte count
|
|
61
|
+
when needed. When the boundary is crossed, successful payloads move behind the
|
|
62
|
+
existing `get_result` page handle while ordered success/failure outcomes and
|
|
63
|
+
bounded failure details remain inline.
|
|
64
|
+
|
|
65
|
+
### Added
|
|
66
|
+
|
|
67
|
+
- **An independent aggregate batch-result cap** (issue #139, PR #141).
|
|
68
|
+
`calls.maxBatchResultBytes` defaults to 100,000 bytes, is validated with the
|
|
69
|
+
ordinary result-cap rules, and applies after every child's global or
|
|
70
|
+
connector-level guard. The exact serialized `{ results, durationMs }`
|
|
71
|
+
envelope is stashed in the existing toolkit-aware result store and pages with
|
|
72
|
+
the same byte offsets and UTF-8 invariants as ordinary guarded results.
|
|
73
|
+
|
|
74
|
+
### Changed
|
|
75
|
+
|
|
76
|
+
- **Lexical tool search recovers from over-specified queries** (issue #137,
|
|
77
|
+
PR #140). Exact, prefix, and all-term ranking remains the first stage. Only
|
|
78
|
+
when an entire scoped search has no match does dependency-free fallback rank
|
|
79
|
+
partial matches by term coverage, tool-name coverage, and stable catalog
|
|
80
|
+
order, marking the response with `matchMode: "partial"`. The behavior is
|
|
81
|
+
shared by `search_tools` and code mode's `connecta.search`; no-overlap
|
|
82
|
+
searches remain empty.
|
|
83
|
+
|
|
84
|
+
### Fixed
|
|
85
|
+
|
|
86
|
+
- **`batch_call` can no longer multiply the inline result boundary by child
|
|
87
|
+
count** (issue #139, PR #141). The complete final envelope is measured before
|
|
88
|
+
emission. Oversized batches return a compact ordered outcome summary plus a
|
|
89
|
+
`get_result` handle, with partial failures still visible inline and successful
|
|
90
|
+
data available through paging. Below-cap batches retain their prior response
|
|
91
|
+
shape.
|
|
92
|
+
|
|
5
93
|
## 0.7.7 — 2026-07-27
|
|
6
94
|
|
|
7
95
|
0.7.7 gives operators explicit downstream OAuth lifecycle controls, makes
|
package/dist/activity.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Logger } from "./types.js";
|
|
2
2
|
export type ActivityCallSource = "call_tool" | "call_destructive_tool" | "batch_call" | "execute_code";
|
|
3
|
-
export type ActivityOutcome = "success" | "error" | "timeout";
|
|
3
|
+
export type ActivityOutcome = "success" | "error" | "timeout" | "cancelled";
|
|
4
4
|
/**
|
|
5
5
|
* Authenticated identity attached to an activity event. `id` is intentionally
|
|
6
6
|
* optional: open deployments and shared bearer tokens cannot honestly identify
|
package/dist/activity.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../src/activity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,MAAM,kBAAkB,GAC1B,WAAW,GACX,uBAAuB,GACvB,YAAY,GACZ,cAAc,CAAC;AAEnB,MAAM,MAAM,eAAe,
|
|
1
|
+
{"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../src/activity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,MAAM,kBAAkB,GAC1B,WAAW,GACX,uBAAuB,GACvB,YAAY,GACZ,cAAc,CAAC;AAEnB,MAAM,MAAM,eAAe,GACvB,SAAS,GACT,OAAO,GACP,SAAS,GACT,WAAW,CAAC;AAEhB;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,CAAC,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,aAAa,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,OAAO,EAAE,eAAe,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,qBAAqB,EAAE,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,0EAA0E;AAC1E,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,qBAAqB,EAAE,OAAO,CAAC,GAAG;IACrE,KAAK,EAAE,iBAAiB,CAAC;CAC1B,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,iFAAiF;AACjF,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,KAAK,EAAE,qBAAqB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5D;AAED,uEAAuE;AACvE,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC1E;AAED,MAAM,WAAW,aAAc,SAAQ,YAAY;IACjD,IAAI,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;CAC/B;AAED,iFAAiF;AACjF,qBAAa,0BAA2B,SAAQ,KAAK;IAC1C,IAAI,SAAgC;;CAK9C;AAED,MAAM,MAAM,gBAAgB,GAAG,CAC7B,KAAK,EAAE,aAAa,KACjB,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAEhC,gFAAgF;AAChF,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IAC5C,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,kBAAkB,GAAG,IAAI,CACnC,qBAAqB,EACnB,aAAa,GACb,UAAU,GACV,SAAS,GACT,QAAQ,GACR,SAAS,GACT,YAAY,GACZ,UAAU,GACV,WAAW,CACd,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,sBAAsB,GAAG,SAAS,EAC3C,KAAK,EAAE,kBAAkB,GACxB,IAAI,CAmCN"}
|
package/dist/activity.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity.js","sourceRoot":"","sources":["../src/activity.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"activity.js","sourceRoot":"","sources":["../src/activity.ts"],"names":[],"mappings":"AA+FA,iFAAiF;AACjF,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IAC1C,IAAI,GAAG,4BAA4B,CAAC;IAE7C;QACE,KAAK,CAAC,yBAAyB,CAAC,CAAC;IACnC,CAAC;CACF;AA+BD;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAA2C,EAC3C,KAAyB;IAEzB,IAAI,CAAC,OAAO;QAAE,OAAO;IACrB,MAAM,KAAK,GAA0B;QACnC,aAAa,EAAE,CAAC;QAChB,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE;QACvB,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACpC,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACrD,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACjD,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1D,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,IAAI;QACnC,aAAa,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO;QACzC,GAAG,CAAC,OAAO,CAAC,YAAY;YACtB,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE;YACxC,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC/D,CAAC;IACF,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,IAAI,OAAQ,MAA2B,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YACvE,OAAO;QACT,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACtD,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;QACH,IAAI,OAAO,CAAC,KAAK;YAAE,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAC;IAClE,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { ConnectorCallError } from "./errors.js";
|
|
2
|
+
import type { ConnectorCallAdmissionInput, ConnectorCallAdmissionPolicy } from "./types.js";
|
|
3
|
+
export type CallAdmissionFailureKind = "concurrency" | "budget" | "cancelled" | "closed" | "partition";
|
|
4
|
+
/**
|
|
5
|
+
* A locally-produced connector-call failure. Extending ConnectorCallError
|
|
6
|
+
* preserves the public error envelope while letting call paths avoid recording
|
|
7
|
+
* a refusal as evidence that the downstream provider is unhealthy.
|
|
8
|
+
*/
|
|
9
|
+
export declare class CallAdmissionError extends ConnectorCallError {
|
|
10
|
+
readonly admissionKind: CallAdmissionFailureKind;
|
|
11
|
+
constructor(admissionKind: CallAdmissionFailureKind, code: ConstructorParameters<typeof ConnectorCallError>[0], message: string, opts?: ConstructorParameters<typeof ConnectorCallError>[2]);
|
|
12
|
+
}
|
|
13
|
+
export declare function isCallAdmissionError(error: unknown): error is CallAdmissionError;
|
|
14
|
+
export interface CallAdmissionPermit {
|
|
15
|
+
/** Time spent in the concurrency queue. Zero for immediate admission. */
|
|
16
|
+
readonly waitMs: number;
|
|
17
|
+
/** Idempotent. */
|
|
18
|
+
release(): void;
|
|
19
|
+
}
|
|
20
|
+
export interface ConnectorCallAdmissionSnapshot {
|
|
21
|
+
rules: number;
|
|
22
|
+
partitions: number;
|
|
23
|
+
active: number;
|
|
24
|
+
queued: number;
|
|
25
|
+
closed: boolean;
|
|
26
|
+
totals: {
|
|
27
|
+
admitted: number;
|
|
28
|
+
queued: number;
|
|
29
|
+
rejected: number;
|
|
30
|
+
rateLimited: number;
|
|
31
|
+
cancelled: number;
|
|
32
|
+
};
|
|
33
|
+
queueWaitMs: {
|
|
34
|
+
count: number;
|
|
35
|
+
total: number;
|
|
36
|
+
max: number;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Per-runtime, per-connector call admission. State contains only bounded
|
|
41
|
+
* partition keys, counters, timestamps, signals, and promise continuations;
|
|
42
|
+
* tool arguments never enter the controller.
|
|
43
|
+
*/
|
|
44
|
+
export declare class ConnectorCallAdmissionController {
|
|
45
|
+
readonly connectorId: string;
|
|
46
|
+
private readonly maxConcurrency;
|
|
47
|
+
private readonly maxQueueSize;
|
|
48
|
+
private readonly queueTimeoutMs;
|
|
49
|
+
private readonly retryAfterMs;
|
|
50
|
+
private readonly maxPartitions;
|
|
51
|
+
private readonly budget;
|
|
52
|
+
private readonly partitionKey;
|
|
53
|
+
private readonly partitions;
|
|
54
|
+
private closed;
|
|
55
|
+
private admittedTotal;
|
|
56
|
+
private queuedTotal;
|
|
57
|
+
private rejectedTotal;
|
|
58
|
+
private rateLimitedTotal;
|
|
59
|
+
private cancelledTotal;
|
|
60
|
+
private queueWaitCount;
|
|
61
|
+
private queueWaitTotalMs;
|
|
62
|
+
private queueWaitMaxMs;
|
|
63
|
+
constructor(connectorId: string, policy: ConnectorCallAdmissionPolicy);
|
|
64
|
+
acquire(input: Readonly<ConnectorCallAdmissionInput> & {
|
|
65
|
+
signal?: AbortSignal;
|
|
66
|
+
}): Promise<CallAdmissionPermit>;
|
|
67
|
+
snapshot(): ConnectorCallAdmissionSnapshot;
|
|
68
|
+
close(): void;
|
|
69
|
+
private admit;
|
|
70
|
+
private pump;
|
|
71
|
+
private pruneBudget;
|
|
72
|
+
private budgetRetryAfterMs;
|
|
73
|
+
private evictIdlePartitions;
|
|
74
|
+
private maybeDeletePartition;
|
|
75
|
+
private removeWaiter;
|
|
76
|
+
private cleanupWaiter;
|
|
77
|
+
private concurrencyLimited;
|
|
78
|
+
private budgetLimited;
|
|
79
|
+
private cancelled;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=call-admission.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"call-admission.d.ts","sourceRoot":"","sources":["../src/call-admission.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import { ConnectorCallError } from "./errors.js";
|
|
2
|
+
const DEFAULT_MAX_QUEUE_SIZE = 32;
|
|
3
|
+
const DEFAULT_QUEUE_TIMEOUT_MS = 5_000;
|
|
4
|
+
const DEFAULT_RETRY_AFTER_MS = 1_000;
|
|
5
|
+
const DEFAULT_MAX_PARTITIONS = 1_024;
|
|
6
|
+
const MAX_PARTITION_KEY_BYTES = 128;
|
|
7
|
+
const DEFAULT_PARTITION_KEY = "";
|
|
8
|
+
const enc = new TextEncoder();
|
|
9
|
+
/**
|
|
10
|
+
* A locally-produced connector-call failure. Extending ConnectorCallError
|
|
11
|
+
* preserves the public error envelope while letting call paths avoid recording
|
|
12
|
+
* a refusal as evidence that the downstream provider is unhealthy.
|
|
13
|
+
*/
|
|
14
|
+
export class CallAdmissionError extends ConnectorCallError {
|
|
15
|
+
admissionKind;
|
|
16
|
+
constructor(admissionKind, code, message, opts = {}) {
|
|
17
|
+
super(code, message, opts);
|
|
18
|
+
this.admissionKind = admissionKind;
|
|
19
|
+
this.name = "CallAdmissionError";
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function isCallAdmissionError(error) {
|
|
23
|
+
return error instanceof CallAdmissionError;
|
|
24
|
+
}
|
|
25
|
+
function positiveWhole(value, name) {
|
|
26
|
+
if (!Number.isFinite(value) || !Number.isInteger(value) || value < 1) {
|
|
27
|
+
throw new TypeError(`${name} must be a positive whole number.`);
|
|
28
|
+
}
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
31
|
+
function nonNegativeWhole(value, name) {
|
|
32
|
+
if (!Number.isFinite(value) || !Number.isInteger(value) || value < 0) {
|
|
33
|
+
throw new TypeError(`${name} must be a non-negative whole number.`);
|
|
34
|
+
}
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Per-runtime, per-connector call admission. State contains only bounded
|
|
39
|
+
* partition keys, counters, timestamps, signals, and promise continuations;
|
|
40
|
+
* tool arguments never enter the controller.
|
|
41
|
+
*/
|
|
42
|
+
export class ConnectorCallAdmissionController {
|
|
43
|
+
connectorId;
|
|
44
|
+
maxConcurrency;
|
|
45
|
+
maxQueueSize;
|
|
46
|
+
queueTimeoutMs;
|
|
47
|
+
retryAfterMs;
|
|
48
|
+
maxPartitions;
|
|
49
|
+
budget;
|
|
50
|
+
partitionKey;
|
|
51
|
+
partitions = new Map();
|
|
52
|
+
closed = false;
|
|
53
|
+
admittedTotal = 0;
|
|
54
|
+
queuedTotal = 0;
|
|
55
|
+
rejectedTotal = 0;
|
|
56
|
+
rateLimitedTotal = 0;
|
|
57
|
+
cancelledTotal = 0;
|
|
58
|
+
queueWaitCount = 0;
|
|
59
|
+
queueWaitTotalMs = 0;
|
|
60
|
+
queueWaitMaxMs = 0;
|
|
61
|
+
constructor(connectorId, policy) {
|
|
62
|
+
this.connectorId = connectorId;
|
|
63
|
+
if (!Array.isArray(policy.rules) || policy.rules.length !== 1) {
|
|
64
|
+
throw new TypeError(`connector "${connectorId}" callAdmission.rules must contain exactly one rule in this release.`);
|
|
65
|
+
}
|
|
66
|
+
const rule = policy.rules[0];
|
|
67
|
+
if (rule.maxConcurrency === undefined &&
|
|
68
|
+
rule.budget === undefined) {
|
|
69
|
+
throw new TypeError(`connector "${connectorId}" callAdmission rule must declare maxConcurrency or budget.`);
|
|
70
|
+
}
|
|
71
|
+
this.maxConcurrency =
|
|
72
|
+
rule.maxConcurrency === undefined
|
|
73
|
+
? undefined
|
|
74
|
+
: positiveWhole(rule.maxConcurrency, `connector "${connectorId}" callAdmission maxConcurrency`);
|
|
75
|
+
if (this.maxConcurrency === undefined &&
|
|
76
|
+
(rule.maxQueueSize !== undefined ||
|
|
77
|
+
rule.queueTimeoutMs !== undefined ||
|
|
78
|
+
rule.retryAfterMs !== undefined)) {
|
|
79
|
+
throw new TypeError(`connector "${connectorId}" callAdmission queue settings require maxConcurrency.`);
|
|
80
|
+
}
|
|
81
|
+
this.maxQueueSize = nonNegativeWhole(rule.maxQueueSize ?? DEFAULT_MAX_QUEUE_SIZE, `connector "${connectorId}" callAdmission maxQueueSize`);
|
|
82
|
+
this.queueTimeoutMs = positiveWhole(rule.queueTimeoutMs ?? DEFAULT_QUEUE_TIMEOUT_MS, `connector "${connectorId}" callAdmission queueTimeoutMs`);
|
|
83
|
+
this.retryAfterMs = nonNegativeWhole(rule.retryAfterMs ?? DEFAULT_RETRY_AFTER_MS, `connector "${connectorId}" callAdmission retryAfterMs`);
|
|
84
|
+
this.maxPartitions = positiveWhole(policy.maxPartitions ?? DEFAULT_MAX_PARTITIONS, `connector "${connectorId}" callAdmission maxPartitions`);
|
|
85
|
+
if (rule.budget) {
|
|
86
|
+
if (rule.budget.kind !== "rolling-window") {
|
|
87
|
+
throw new TypeError(`connector "${connectorId}" callAdmission budget kind must be "rolling-window".`);
|
|
88
|
+
}
|
|
89
|
+
const maxCalls = positiveWhole(rule.budget.maxCalls, `connector "${connectorId}" callAdmission budget.maxCalls`);
|
|
90
|
+
const windowMs = positiveWhole(rule.budget.windowMs, `connector "${connectorId}" callAdmission budget.windowMs`);
|
|
91
|
+
this.budget = { maxCalls, windowMs };
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
this.budget = undefined;
|
|
95
|
+
}
|
|
96
|
+
this.partitionKey = rule.partitionKey;
|
|
97
|
+
}
|
|
98
|
+
acquire(input) {
|
|
99
|
+
// Copy the signal out before constructing any waiter closure. Referencing
|
|
100
|
+
// `input` from a queued callback would retain its `args`, defeating the
|
|
101
|
+
// limiter's payload-free state contract.
|
|
102
|
+
const signal = input.signal;
|
|
103
|
+
if (this.closed) {
|
|
104
|
+
return Promise.reject(new CallAdmissionError("closed", "unavailable", `Connector "${this.connectorId}" call admission is closed.`));
|
|
105
|
+
}
|
|
106
|
+
if (signal?.aborted) {
|
|
107
|
+
this.cancelledTotal++;
|
|
108
|
+
return Promise.reject(this.cancelled(signal));
|
|
109
|
+
}
|
|
110
|
+
let key;
|
|
111
|
+
try {
|
|
112
|
+
key = this.partitionKey
|
|
113
|
+
? this.partitionKey({
|
|
114
|
+
toolName: input.toolName,
|
|
115
|
+
args: input.args,
|
|
116
|
+
})
|
|
117
|
+
: DEFAULT_PARTITION_KEY;
|
|
118
|
+
}
|
|
119
|
+
catch (cause) {
|
|
120
|
+
this.rejectedTotal++;
|
|
121
|
+
return Promise.reject(new CallAdmissionError("partition", "connector_call_failed", `Connector "${this.connectorId}" call-admission partitionKey threw.`, { cause }));
|
|
122
|
+
}
|
|
123
|
+
if (typeof key !== "string" ||
|
|
124
|
+
enc.encode(key).length > MAX_PARTITION_KEY_BYTES) {
|
|
125
|
+
this.rejectedTotal++;
|
|
126
|
+
return Promise.reject(new CallAdmissionError("partition", "connector_call_failed", `Connector "${this.connectorId}" call-admission partitionKey must return a string of at most ${MAX_PARTITION_KEY_BYTES} UTF-8 bytes.`));
|
|
127
|
+
}
|
|
128
|
+
// A partition callback is operator code and may synchronously abort the
|
|
129
|
+
// caller. Recheck after it returns so that cancellation cannot consume a
|
|
130
|
+
// budget entry or concurrency slot.
|
|
131
|
+
if (signal?.aborted) {
|
|
132
|
+
this.cancelledTotal++;
|
|
133
|
+
return Promise.reject(this.cancelled(signal));
|
|
134
|
+
}
|
|
135
|
+
const now = Date.now();
|
|
136
|
+
let state = this.partitions.get(key);
|
|
137
|
+
if (!state) {
|
|
138
|
+
this.evictIdlePartitions(now);
|
|
139
|
+
if (this.partitions.size >= this.maxPartitions) {
|
|
140
|
+
this.rejectedTotal++;
|
|
141
|
+
return Promise.reject(new CallAdmissionError("partition", "rate_limited", `Connector "${this.connectorId}" call-admission partition capacity is exhausted.`, { retryAfterMs: this.retryAfterMs }));
|
|
142
|
+
}
|
|
143
|
+
state = {
|
|
144
|
+
active: 0,
|
|
145
|
+
waiters: [],
|
|
146
|
+
admittedAt: [],
|
|
147
|
+
};
|
|
148
|
+
this.partitions.set(key, state);
|
|
149
|
+
}
|
|
150
|
+
this.pruneBudget(state, now);
|
|
151
|
+
const budgetRetryAfterMs = this.budgetRetryAfterMs(state, now);
|
|
152
|
+
if (budgetRetryAfterMs !== undefined) {
|
|
153
|
+
this.rateLimitedTotal++;
|
|
154
|
+
return Promise.reject(this.budgetLimited(budgetRetryAfterMs));
|
|
155
|
+
}
|
|
156
|
+
if (this.maxConcurrency === undefined ||
|
|
157
|
+
state.active < this.maxConcurrency) {
|
|
158
|
+
return Promise.resolve(this.admit(state, now, 0));
|
|
159
|
+
}
|
|
160
|
+
if (state.waiters.length >= this.maxQueueSize) {
|
|
161
|
+
this.rejectedTotal++;
|
|
162
|
+
return Promise.reject(this.concurrencyLimited("queue is full"));
|
|
163
|
+
}
|
|
164
|
+
return new Promise((resolve, reject) => {
|
|
165
|
+
const waiter = {
|
|
166
|
+
queuedAt: now,
|
|
167
|
+
resolve,
|
|
168
|
+
reject,
|
|
169
|
+
...(signal ? { signal } : {}),
|
|
170
|
+
};
|
|
171
|
+
waiter.onAbort = () => {
|
|
172
|
+
if (!this.removeWaiter(state, waiter))
|
|
173
|
+
return;
|
|
174
|
+
this.cleanupWaiter(waiter);
|
|
175
|
+
this.cancelledTotal++;
|
|
176
|
+
reject(this.cancelled(signal));
|
|
177
|
+
this.maybeDeletePartition(key, state, Date.now());
|
|
178
|
+
};
|
|
179
|
+
waiter.timer = setTimeout(() => {
|
|
180
|
+
if (!this.removeWaiter(state, waiter))
|
|
181
|
+
return;
|
|
182
|
+
this.cleanupWaiter(waiter);
|
|
183
|
+
this.rejectedTotal++;
|
|
184
|
+
reject(this.concurrencyLimited(`queue wait exceeded ${this.queueTimeoutMs}ms`));
|
|
185
|
+
this.maybeDeletePartition(key, state, Date.now());
|
|
186
|
+
}, this.queueTimeoutMs);
|
|
187
|
+
state.waiters.push(waiter);
|
|
188
|
+
this.queuedTotal++;
|
|
189
|
+
signal?.addEventListener("abort", waiter.onAbort, { once: true });
|
|
190
|
+
// Close the check-to-listener race: an abort before registration is not
|
|
191
|
+
// replayed by AbortSignal, so inspect it once after the waiter is fully
|
|
192
|
+
// removable and its timer is installed.
|
|
193
|
+
if (signal?.aborted)
|
|
194
|
+
waiter.onAbort();
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
snapshot() {
|
|
198
|
+
let active = 0;
|
|
199
|
+
let queued = 0;
|
|
200
|
+
for (const state of this.partitions.values()) {
|
|
201
|
+
active += state.active;
|
|
202
|
+
queued += state.waiters.length;
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
rules: 1,
|
|
206
|
+
partitions: this.partitions.size,
|
|
207
|
+
active,
|
|
208
|
+
queued,
|
|
209
|
+
closed: this.closed,
|
|
210
|
+
totals: {
|
|
211
|
+
admitted: this.admittedTotal,
|
|
212
|
+
queued: this.queuedTotal,
|
|
213
|
+
rejected: this.rejectedTotal,
|
|
214
|
+
rateLimited: this.rateLimitedTotal,
|
|
215
|
+
cancelled: this.cancelledTotal,
|
|
216
|
+
},
|
|
217
|
+
queueWaitMs: {
|
|
218
|
+
count: this.queueWaitCount,
|
|
219
|
+
total: this.queueWaitTotalMs,
|
|
220
|
+
max: this.queueWaitMaxMs,
|
|
221
|
+
},
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
close() {
|
|
225
|
+
if (this.closed)
|
|
226
|
+
return;
|
|
227
|
+
this.closed = true;
|
|
228
|
+
for (const state of this.partitions.values()) {
|
|
229
|
+
for (const waiter of state.waiters.splice(0)) {
|
|
230
|
+
this.cleanupWaiter(waiter);
|
|
231
|
+
waiter.reject(new CallAdmissionError("closed", "unavailable", `Connector "${this.connectorId}" call admission is closed.`));
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
admit(state, now, waitMs) {
|
|
236
|
+
state.active++;
|
|
237
|
+
if (this.budget)
|
|
238
|
+
state.admittedAt.push(now);
|
|
239
|
+
this.admittedTotal++;
|
|
240
|
+
if (waitMs > 0) {
|
|
241
|
+
this.queueWaitCount++;
|
|
242
|
+
this.queueWaitTotalMs += waitMs;
|
|
243
|
+
this.queueWaitMaxMs = Math.max(this.queueWaitMaxMs, waitMs);
|
|
244
|
+
}
|
|
245
|
+
let released = false;
|
|
246
|
+
return {
|
|
247
|
+
waitMs,
|
|
248
|
+
release: () => {
|
|
249
|
+
if (released)
|
|
250
|
+
return;
|
|
251
|
+
released = true;
|
|
252
|
+
if (state.active > 0)
|
|
253
|
+
state.active--;
|
|
254
|
+
this.pump(state);
|
|
255
|
+
},
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
pump(state) {
|
|
259
|
+
if (this.closed || this.maxConcurrency === undefined)
|
|
260
|
+
return;
|
|
261
|
+
while (state.active < this.maxConcurrency &&
|
|
262
|
+
state.waiters.length > 0) {
|
|
263
|
+
const waiter = state.waiters.shift();
|
|
264
|
+
this.cleanupWaiter(waiter);
|
|
265
|
+
if (waiter.signal?.aborted) {
|
|
266
|
+
this.cancelledTotal++;
|
|
267
|
+
waiter.reject(this.cancelled(waiter.signal));
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
const now = Date.now();
|
|
271
|
+
this.pruneBudget(state, now);
|
|
272
|
+
const retryAfterMs = this.budgetRetryAfterMs(state, now);
|
|
273
|
+
if (retryAfterMs !== undefined) {
|
|
274
|
+
this.rateLimitedTotal++;
|
|
275
|
+
waiter.reject(this.budgetLimited(retryAfterMs));
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
const waitMs = Math.max(0, now - waiter.queuedAt);
|
|
279
|
+
waiter.resolve(this.admit(state, now, waitMs));
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
pruneBudget(state, now) {
|
|
283
|
+
const budget = this.budget;
|
|
284
|
+
if (!budget || state.admittedAt.length === 0)
|
|
285
|
+
return;
|
|
286
|
+
let expired = 0;
|
|
287
|
+
while (expired < state.admittedAt.length &&
|
|
288
|
+
state.admittedAt[expired] + budget.windowMs <= now) {
|
|
289
|
+
expired++;
|
|
290
|
+
}
|
|
291
|
+
if (expired > 0)
|
|
292
|
+
state.admittedAt.splice(0, expired);
|
|
293
|
+
}
|
|
294
|
+
budgetRetryAfterMs(state, now) {
|
|
295
|
+
const budget = this.budget;
|
|
296
|
+
if (!budget || state.admittedAt.length < budget.maxCalls) {
|
|
297
|
+
return undefined;
|
|
298
|
+
}
|
|
299
|
+
return Math.max(0, state.admittedAt[0] + budget.windowMs - now);
|
|
300
|
+
}
|
|
301
|
+
evictIdlePartitions(now) {
|
|
302
|
+
for (const [key, state] of this.partitions) {
|
|
303
|
+
this.pruneBudget(state, now);
|
|
304
|
+
this.maybeDeletePartition(key, state, now);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
maybeDeletePartition(key, state, now) {
|
|
308
|
+
this.pruneBudget(state, now);
|
|
309
|
+
if (state.active === 0 &&
|
|
310
|
+
state.waiters.length === 0 &&
|
|
311
|
+
state.admittedAt.length === 0) {
|
|
312
|
+
this.partitions.delete(key);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
removeWaiter(state, waiter) {
|
|
316
|
+
const index = state.waiters.indexOf(waiter);
|
|
317
|
+
if (index < 0)
|
|
318
|
+
return false;
|
|
319
|
+
state.waiters.splice(index, 1);
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
cleanupWaiter(waiter) {
|
|
323
|
+
if (waiter.timer !== undefined)
|
|
324
|
+
clearTimeout(waiter.timer);
|
|
325
|
+
if (waiter.onAbort) {
|
|
326
|
+
waiter.signal?.removeEventListener("abort", waiter.onAbort);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
concurrencyLimited(reason) {
|
|
330
|
+
return new CallAdmissionError("concurrency", "rate_limited", `Connector "${this.connectorId}" call concurrency ${reason}.`, { retryAfterMs: this.retryAfterMs });
|
|
331
|
+
}
|
|
332
|
+
budgetLimited(retryAfterMs) {
|
|
333
|
+
return new CallAdmissionError("budget", "rate_limited", `Connector "${this.connectorId}" rolling call budget is exhausted.`, { retryAfterMs });
|
|
334
|
+
}
|
|
335
|
+
cancelled(signal) {
|
|
336
|
+
return new CallAdmissionError("cancelled", "timeout", `Connector "${this.connectorId}" call was cancelled before admission.`, { cause: signal.reason });
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
//# sourceMappingURL=call-admission.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"call-admission.js","sourceRoot":"","sources":["../src/call-admission.ts"],"names":[],"mappings":"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"}
|
package/dist/catalog.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { JsonSchema, ToolDef } from "./types.js";
|
|
2
2
|
export declare function summarizeDescription(text: string | undefined, full: boolean): string | undefined;
|
|
3
|
-
|
|
4
|
-
export
|
|
3
|
+
export type LexicalMatchMode = "all" | "partial";
|
|
4
|
+
export interface RankedTool {
|
|
5
5
|
tool: ToolDef;
|
|
6
6
|
score: number;
|
|
7
7
|
order: number;
|
|
8
|
-
}
|
|
8
|
+
}
|
|
9
|
+
/** Rank a connector's tools while caching its normalized plain-data index. */
|
|
10
|
+
export declare function rankTools(tools: ToolDef[], query: string, mode?: LexicalMatchMode): RankedTool[];
|
|
9
11
|
/** Render and cache a compact TypeScript-like representation of JSON Schema. */
|
|
10
12
|
export declare function compactSchema(schema: JsonSchema): string;
|
|
11
13
|
//# sourceMappingURL=catalog.d.ts.map
|
package/dist/catalog.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAItD,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,IAAI,EAAE,OAAO,GACZ,MAAM,GAAG,SAAS,CAMpB;
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAItD,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,IAAI,EAAE,OAAO,GACZ,MAAM,GAAG,SAAS,CAMpB;AAYD,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,SAAS,CAAC;AAEjD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAkDD,8EAA8E;AAC9E,wBAAgB,SAAS,CACvB,KAAK,EAAE,OAAO,EAAE,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,gBAAwB,GAC7B,UAAU,EAAE,CASd;AAuID,gFAAgF;AAChF,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAexD"}
|
package/dist/catalog.js
CHANGED
|
@@ -25,12 +25,21 @@ function documentsFor(tools) {
|
|
|
25
25
|
}
|
|
26
26
|
return docs;
|
|
27
27
|
}
|
|
28
|
-
function scoreDocument(doc, phrase, terms) {
|
|
28
|
+
function scoreDocument(doc, phrase, terms, mode) {
|
|
29
29
|
if (!phrase)
|
|
30
30
|
return 0;
|
|
31
31
|
const haystack = `${doc.name} ${doc.description}`;
|
|
32
|
-
|
|
32
|
+
const matchedTerms = terms.filter((term) => haystack.includes(term));
|
|
33
|
+
if (mode === "all" && matchedTerms.length !== terms.length)
|
|
33
34
|
return null;
|
|
35
|
+
if (mode === "partial") {
|
|
36
|
+
if (matchedTerms.length === 0)
|
|
37
|
+
return null;
|
|
38
|
+
const nameMatches = matchedTerms.filter((term) => doc.name.includes(term)).length;
|
|
39
|
+
// Coverage wins first, then the number of those terms found in the tool
|
|
40
|
+
// name. Catalog order breaks the remaining ties at the caller.
|
|
41
|
+
return matchedTerms.length * 1_000 + nameMatches;
|
|
42
|
+
}
|
|
34
43
|
let score = 0;
|
|
35
44
|
if (doc.name === phrase)
|
|
36
45
|
score += 1_000;
|
|
@@ -51,12 +60,12 @@ function scoreDocument(doc, phrase, terms) {
|
|
|
51
60
|
return score;
|
|
52
61
|
}
|
|
53
62
|
/** Rank a connector's tools while caching its normalized plain-data index. */
|
|
54
|
-
export function rankTools(tools, query) {
|
|
63
|
+
export function rankTools(tools, query, mode = "all") {
|
|
55
64
|
const phrase = normalized(query);
|
|
56
65
|
const terms = phrase.split(/\s+/).filter(Boolean);
|
|
57
66
|
const ranked = [];
|
|
58
67
|
documentsFor(tools).forEach((doc, order) => {
|
|
59
|
-
const score = scoreDocument(doc, phrase, terms);
|
|
68
|
+
const score = scoreDocument(doc, phrase, terms, mode);
|
|
60
69
|
if (score !== null)
|
|
61
70
|
ranked.push({ tool: doc.tool, score, order });
|
|
62
71
|
});
|