@nxisai/agent-harness 0.2.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/README.md +434 -0
- package/dist/a2ui/cards.d.ts +55 -0
- package/dist/a2ui/cards.d.ts.map +1 -0
- package/dist/a2ui/cards.js +133 -0
- package/dist/a2ui/cards.js.map +1 -0
- package/dist/a2ui/emit.d.ts +33 -0
- package/dist/a2ui/emit.d.ts.map +1 -0
- package/dist/a2ui/emit.js +116 -0
- package/dist/a2ui/emit.js.map +1 -0
- package/dist/a2ui/form.d.ts +20 -0
- package/dist/a2ui/form.d.ts.map +1 -0
- package/dist/a2ui/form.js +92 -0
- package/dist/a2ui/form.js.map +1 -0
- package/dist/a2ui/host.d.ts +34 -0
- package/dist/a2ui/host.d.ts.map +1 -0
- package/dist/a2ui/host.js +47 -0
- package/dist/a2ui/host.js.map +1 -0
- package/dist/a2ui/index.d.ts +23 -0
- package/dist/a2ui/index.d.ts.map +1 -0
- package/dist/a2ui/index.js +20 -0
- package/dist/a2ui/index.js.map +1 -0
- package/dist/a2ui/stepper.d.ts +26 -0
- package/dist/a2ui/stepper.d.ts.map +1 -0
- package/dist/a2ui/stepper.js +162 -0
- package/dist/a2ui/stepper.js.map +1 -0
- package/dist/a2ui/theme.d.ts +21 -0
- package/dist/a2ui/theme.d.ts.map +1 -0
- package/dist/a2ui/theme.js +134 -0
- package/dist/a2ui/theme.js.map +1 -0
- package/dist/a2ui/to-v09.d.ts +31 -0
- package/dist/a2ui/to-v09.d.ts.map +1 -0
- package/dist/a2ui/to-v09.js +104 -0
- package/dist/a2ui/to-v09.js.map +1 -0
- package/dist/engine.d.ts +209 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +505 -0
- package/dist/engine.js.map +1 -0
- package/dist/harness/harness.d.ts +284 -0
- package/dist/harness/harness.d.ts.map +1 -0
- package/dist/harness/harness.js +568 -0
- package/dist/harness/harness.js.map +1 -0
- package/dist/harness/plan.d.ts +32 -0
- package/dist/harness/plan.d.ts.map +1 -0
- package/dist/harness/plan.js +68 -0
- package/dist/harness/plan.js.map +1 -0
- package/dist/harness/policy.d.ts +49 -0
- package/dist/harness/policy.d.ts.map +1 -0
- package/dist/harness/policy.js +34 -0
- package/dist/harness/policy.js.map +1 -0
- package/dist/harness/renderer.d.ts +163 -0
- package/dist/harness/renderer.d.ts.map +1 -0
- package/dist/harness/renderer.js +12 -0
- package/dist/harness/renderer.js.map +1 -0
- package/dist/harness/router/coordinator.d.ts +120 -0
- package/dist/harness/router/coordinator.d.ts.map +1 -0
- package/dist/harness/router/coordinator.js +145 -0
- package/dist/harness/router/coordinator.js.map +1 -0
- package/dist/harness/router/rules.d.ts +48 -0
- package/dist/harness/router/rules.d.ts.map +1 -0
- package/dist/harness/router/rules.js +38 -0
- package/dist/harness/router/rules.js.map +1 -0
- package/dist/harness/slots.d.ts +73 -0
- package/dist/harness/slots.d.ts.map +1 -0
- package/dist/harness/slots.js +68 -0
- package/dist/harness/slots.js.map +1 -0
- package/dist/harness/tools/bridge.d.ts +71 -0
- package/dist/harness/tools/bridge.d.ts.map +1 -0
- package/dist/harness/tools/bridge.js +271 -0
- package/dist/harness/tools/bridge.js.map +1 -0
- package/dist/harness/tools/client.d.ts +11 -0
- package/dist/harness/tools/client.d.ts.map +1 -0
- package/dist/harness/tools/client.js +21 -0
- package/dist/harness/tools/client.js.map +1 -0
- package/dist/harness/tools/discovery.d.ts +13 -0
- package/dist/harness/tools/discovery.d.ts.map +1 -0
- package/dist/harness/tools/discovery.js +43 -0
- package/dist/harness/tools/discovery.js.map +1 -0
- package/dist/harness/tools/local-context.d.ts +38 -0
- package/dist/harness/tools/local-context.d.ts.map +1 -0
- package/dist/harness/tools/local-context.js +55 -0
- package/dist/harness/tools/local-context.js.map +1 -0
- package/dist/harness/tools/schema.d.ts +52 -0
- package/dist/harness/tools/schema.d.ts.map +1 -0
- package/dist/harness/tools/schema.js +175 -0
- package/dist/harness/tools/schema.js.map +1 -0
- package/dist/harness/tools/source.d.ts +65 -0
- package/dist/harness/tools/source.d.ts.map +1 -0
- package/dist/harness/tools/source.js +89 -0
- package/dist/harness/tools/source.js.map +1 -0
- package/dist/harness/tools/webmcp.d.ts +50 -0
- package/dist/harness/tools/webmcp.d.ts.map +1 -0
- package/dist/harness/tools/webmcp.js +114 -0
- package/dist/harness/tools/webmcp.js.map +1 -0
- package/dist/index.d.ts +49 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/types.d.ts +123 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +2 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/types.d.ts +223 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/ui/agent-fullscreen.d.ts +41 -0
- package/dist/ui/agent-fullscreen.d.ts.map +1 -0
- package/dist/ui/agent-fullscreen.js +2821 -0
- package/dist/ui/agent-fullscreen.js.map +1 -0
- package/dist/ui/config.d.ts +88 -0
- package/dist/ui/config.d.ts.map +1 -0
- package/dist/ui/config.js +96 -0
- package/dist/ui/config.js.map +1 -0
- package/dist/ui/index.d.ts +22 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +19 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/tailwind.generated.d.ts +2 -0
- package/dist/ui/tailwind.generated.d.ts.map +1 -0
- package/dist/ui/tailwind.generated.js +3 -0
- package/dist/ui/tailwind.generated.js.map +1 -0
- package/dist/webmcp-contract.d.ts +57 -0
- package/dist/webmcp-contract.d.ts.map +1 -0
- package/dist/webmcp-contract.js +11 -0
- package/dist/webmcp-contract.js.map +1 -0
- package/package.json +39 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pattern-based routing, used before falling back to a model classification.
|
|
3
|
+
*
|
|
4
|
+
* Matching a table of regular expressions costs microseconds, where a
|
|
5
|
+
* classification pass costs a generation. Rules run first and may abstain by
|
|
6
|
+
* returning a null route, which is what tells {@link AgentCoordinator} that a
|
|
7
|
+
* model pass is worth its cost.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
/** One pattern, and the agent it votes for. */
|
|
12
|
+
export interface RouteRule {
|
|
13
|
+
/** The agent this rule votes for. */
|
|
14
|
+
route: string;
|
|
15
|
+
/** Tested against the goal, lower-cased. */
|
|
16
|
+
match: RegExp;
|
|
17
|
+
/**
|
|
18
|
+
* How much this rule's vote counts. Defaults to 1.
|
|
19
|
+
*
|
|
20
|
+
* Raise it so a specific phrase outscores a general one when both match.
|
|
21
|
+
*/
|
|
22
|
+
weight?: number;
|
|
23
|
+
/** A note on the rule's purpose, carried through to {@link RouteDecision}. */
|
|
24
|
+
because?: string;
|
|
25
|
+
}
|
|
26
|
+
/** The result of scoring a goal against a rule table. */
|
|
27
|
+
export interface RouteDecision {
|
|
28
|
+
/** The winning agent, or null when no rule matched or two rules tied. */
|
|
29
|
+
route: string | null;
|
|
30
|
+
/** Total score per route, highest first. Empty when nothing matched. */
|
|
31
|
+
scores: [string, number][];
|
|
32
|
+
/** Every rule that matched, in table order. */
|
|
33
|
+
matched: RouteRule[];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Score a goal against a rule table and return the highest-scoring agent.
|
|
37
|
+
*
|
|
38
|
+
* Ties abstain rather than picking arbitrarily, since routing to an agent that
|
|
39
|
+
* lacks the required tool is more costly than the model pass that resolves the
|
|
40
|
+
* ambiguity.
|
|
41
|
+
*
|
|
42
|
+
* @param goal - The user's message. Matched lower-cased.
|
|
43
|
+
* @param rules - The table to score against.
|
|
44
|
+
* @returns The winning route, or a null route when nothing matched or the top
|
|
45
|
+
* two scores are equal.
|
|
46
|
+
*/
|
|
47
|
+
export declare function matchRoute(goal: string, rules: RouteRule[]): RouteDecision;
|
|
48
|
+
//# sourceMappingURL=rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../../src/harness/router/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,+CAA+C;AAC/C,MAAM,WAAW,SAAS;IACxB,qCAAqC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IAChB;;;;SAIK;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,yDAAyD;AACzD,MAAM,WAAW,aAAa;IAC5B,yEAAyE;IACzE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,wEAAwE;IACxE,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;IAC3B,+CAA+C;IAC/C,OAAO,EAAE,SAAS,EAAE,CAAC;CACtB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,aAAa,CAe1E"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pattern-based routing, used before falling back to a model classification.
|
|
3
|
+
*
|
|
4
|
+
* Matching a table of regular expressions costs microseconds, where a
|
|
5
|
+
* classification pass costs a generation. Rules run first and may abstain by
|
|
6
|
+
* returning a null route, which is what tells {@link AgentCoordinator} that a
|
|
7
|
+
* model pass is worth its cost.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Score a goal against a rule table and return the highest-scoring agent.
|
|
13
|
+
*
|
|
14
|
+
* Ties abstain rather than picking arbitrarily, since routing to an agent that
|
|
15
|
+
* lacks the required tool is more costly than the model pass that resolves the
|
|
16
|
+
* ambiguity.
|
|
17
|
+
*
|
|
18
|
+
* @param goal - The user's message. Matched lower-cased.
|
|
19
|
+
* @param rules - The table to score against.
|
|
20
|
+
* @returns The winning route, or a null route when nothing matched or the top
|
|
21
|
+
* two scores are equal.
|
|
22
|
+
*/
|
|
23
|
+
export function matchRoute(goal, rules) {
|
|
24
|
+
const text = goal.toLowerCase();
|
|
25
|
+
const matched = rules.filter((r) => r.match.test(text));
|
|
26
|
+
const totals = new Map();
|
|
27
|
+
for (const rule of matched) {
|
|
28
|
+
totals.set(rule.route, (totals.get(rule.route) ?? 0) + (rule.weight ?? 1));
|
|
29
|
+
}
|
|
30
|
+
const scores = [...totals.entries()].sort((a, b) => b[1] - a[1]);
|
|
31
|
+
if (!scores.length)
|
|
32
|
+
return { route: null, scores, matched };
|
|
33
|
+
if (scores.length > 1 && scores[0][1] === scores[1][1]) {
|
|
34
|
+
return { route: null, scores, matched };
|
|
35
|
+
}
|
|
36
|
+
return { route: scores[0][0], scores, matched };
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../../../src/harness/router/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA4BH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,KAAkB;IACzD,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAChC,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAExD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7E,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACjE,IAAI,CAAC,MAAM,CAAC,MAAM;QAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IAC5D,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IAC1C,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merges every known source of a tool's arguments and reports what is missing.
|
|
3
|
+
*
|
|
4
|
+
* Sources merge by precedence, most authoritative last:
|
|
5
|
+
*
|
|
6
|
+
* ```
|
|
7
|
+
* schema defaults < page context < saved profile < model args
|
|
8
|
+
* ```
|
|
9
|
+
*
|
|
10
|
+
* Model arguments win because they encode what the user has just asked for, so
|
|
11
|
+
* an explicit value in the request overrides a stored preference.
|
|
12
|
+
*
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
import type { JsonSchema } from '../types.js';
|
|
16
|
+
/** One argument of a tool call, with its value and where that value came from. */
|
|
17
|
+
export interface Slot {
|
|
18
|
+
/** Property key in the flat, model-facing schema. */
|
|
19
|
+
name: string;
|
|
20
|
+
/** The property's JSON Schema, used for labels, types and enums. */
|
|
21
|
+
schema: JsonSchema;
|
|
22
|
+
/** Whether the tool's schema lists this property as required. */
|
|
23
|
+
required: boolean;
|
|
24
|
+
/** Which source supplied {@link Slot.value}; `'none'` when nothing did. */
|
|
25
|
+
source: 'model' | 'profile' | 'context' | 'default' | 'none';
|
|
26
|
+
/** The resolved value, or `undefined` when `source` is `'none'`. */
|
|
27
|
+
value: unknown;
|
|
28
|
+
}
|
|
29
|
+
/** The outcome of merging every source for one tool call. */
|
|
30
|
+
export interface Resolution {
|
|
31
|
+
/** Every known value, ready to submit when `missing` is empty. */
|
|
32
|
+
values: Record<string, unknown>;
|
|
33
|
+
/** Required slots nobody supplied: the values to ask for. */
|
|
34
|
+
missing: Slot[];
|
|
35
|
+
/**
|
|
36
|
+
* Optional slots left empty. Never asked about on their own; a write
|
|
37
|
+
* confirmation may still surface them as editable extras.
|
|
38
|
+
*/
|
|
39
|
+
optional: Slot[];
|
|
40
|
+
/** Every slot in the schema, resolved or not. */
|
|
41
|
+
all: Slot[];
|
|
42
|
+
}
|
|
43
|
+
/** The candidate values to merge, in order of increasing precedence. */
|
|
44
|
+
export interface ResolveSources {
|
|
45
|
+
/** Arguments the model supplied in its tool call. */
|
|
46
|
+
modelArgs?: Record<string, unknown>;
|
|
47
|
+
/** Values saved from earlier turns, such as a name or an email address. */
|
|
48
|
+
profile?: Record<string, unknown>;
|
|
49
|
+
/** Values the host page knows, such as the current record. */
|
|
50
|
+
context?: Record<string, unknown>;
|
|
51
|
+
/** Values a human has typed into a live form. Ranks with `modelArgs`. */
|
|
52
|
+
entered?: Record<string, unknown>;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Resolve every property in a schema against the supplied sources.
|
|
56
|
+
*
|
|
57
|
+
* @param schema - The tool's flat input schema.
|
|
58
|
+
* @param sources - Candidate values, merged by the precedence in the module
|
|
59
|
+
* description.
|
|
60
|
+
* @returns The merged values, plus the required and optional slots still empty.
|
|
61
|
+
*/
|
|
62
|
+
export declare function resolveSlots(schema: JsonSchema, sources: ResolveSources): Resolution;
|
|
63
|
+
/**
|
|
64
|
+
* The slots to display on a write confirmation: those with a value.
|
|
65
|
+
*
|
|
66
|
+
* Empty optional slots are omitted, since a confirmation shows what is about
|
|
67
|
+
* to be sent rather than what could have been.
|
|
68
|
+
*
|
|
69
|
+
* @param resolution - A resolution with no remaining gaps.
|
|
70
|
+
* @returns Every slot whose value came from a source.
|
|
71
|
+
*/
|
|
72
|
+
export declare function summarySlots(resolution: Resolution): Slot[];
|
|
73
|
+
//# sourceMappingURL=slots.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slots.d.ts","sourceRoot":"","sources":["../../src/harness/slots.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,kFAAkF;AAClF,MAAM,WAAW,IAAI;IACnB,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,MAAM,EAAE,UAAU,CAAC;IACnB,iEAAiE;IACjE,QAAQ,EAAE,OAAO,CAAC;IAClB,2EAA2E;IAC3E,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;IAC7D,oEAAoE;IACpE,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,6DAA6D;AAC7D,MAAM,WAAW,UAAU;IACzB,kEAAkE;IAClE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,6DAA6D;IAC7D,OAAO,EAAE,IAAI,EAAE,CAAC;IAChB;;;OAGG;IACH,QAAQ,EAAE,IAAI,EAAE,CAAC;IACjB,iDAAiD;IACjD,GAAG,EAAE,IAAI,EAAE,CAAC;CACb;AAED,wEAAwE;AACxE,MAAM,WAAW,cAAc;IAC7B,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAMD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,GAAG,UAAU,CAiCpF;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,EAAE,CAE3D"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merges every known source of a tool's arguments and reports what is missing.
|
|
3
|
+
*
|
|
4
|
+
* Sources merge by precedence, most authoritative last:
|
|
5
|
+
*
|
|
6
|
+
* ```
|
|
7
|
+
* schema defaults < page context < saved profile < model args
|
|
8
|
+
* ```
|
|
9
|
+
*
|
|
10
|
+
* Model arguments win because they encode what the user has just asked for, so
|
|
11
|
+
* an explicit value in the request overrides a stored preference.
|
|
12
|
+
*
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
/** Present and meaningful: not null, not undefined, not whitespace. */
|
|
16
|
+
const isSet = (v) => v !== undefined && v !== null && !(typeof v === 'string' && v.trim() === '');
|
|
17
|
+
/**
|
|
18
|
+
* Resolve every property in a schema against the supplied sources.
|
|
19
|
+
*
|
|
20
|
+
* @param schema - The tool's flat input schema.
|
|
21
|
+
* @param sources - Candidate values, merged by the precedence in the module
|
|
22
|
+
* description.
|
|
23
|
+
* @returns The merged values, plus the required and optional slots still empty.
|
|
24
|
+
*/
|
|
25
|
+
export function resolveSlots(schema, sources) {
|
|
26
|
+
const props = schema.properties ?? {};
|
|
27
|
+
const required = new Set(schema.required ?? []);
|
|
28
|
+
const all = Object.entries(props).map(([name, spec]) => {
|
|
29
|
+
const propSchema = spec ?? {};
|
|
30
|
+
// Highest precedence first; the first hit wins and records its origin.
|
|
31
|
+
const candidates = [
|
|
32
|
+
['model', sources.entered?.[name]],
|
|
33
|
+
['model', sources.modelArgs?.[name]],
|
|
34
|
+
['profile', sources.profile?.[name]],
|
|
35
|
+
['context', sources.context?.[name]],
|
|
36
|
+
['default', propSchema.default],
|
|
37
|
+
];
|
|
38
|
+
for (const [source, value] of candidates) {
|
|
39
|
+
if (isSet(value)) {
|
|
40
|
+
return { name, schema: propSchema, required: required.has(name), source, value };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return { name, schema: propSchema, required: required.has(name), source: 'none', value: undefined };
|
|
44
|
+
});
|
|
45
|
+
const values = {};
|
|
46
|
+
for (const slot of all)
|
|
47
|
+
if (isSet(slot.value))
|
|
48
|
+
values[slot.name] = slot.value;
|
|
49
|
+
return {
|
|
50
|
+
values,
|
|
51
|
+
missing: all.filter(s => s.required && s.source === 'none'),
|
|
52
|
+
optional: all.filter(s => !s.required && s.source === 'none'),
|
|
53
|
+
all,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The slots to display on a write confirmation: those with a value.
|
|
58
|
+
*
|
|
59
|
+
* Empty optional slots are omitted, since a confirmation shows what is about
|
|
60
|
+
* to be sent rather than what could have been.
|
|
61
|
+
*
|
|
62
|
+
* @param resolution - A resolution with no remaining gaps.
|
|
63
|
+
* @returns Every slot whose value came from a source.
|
|
64
|
+
*/
|
|
65
|
+
export function summarySlots(resolution) {
|
|
66
|
+
return resolution.all.filter(s => s.source !== 'none');
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=slots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slots.js","sourceRoot":"","sources":["../../src/harness/slots.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AA6CH,uEAAuE;AACvE,MAAM,KAAK,GAAG,CAAC,CAAU,EAAW,EAAE,CACpC,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAE/E;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,MAAkB,EAAE,OAAuB;IACtE,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;IACtC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IAEhD,MAAM,GAAG,GAAW,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;QAC7D,MAAM,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC;QAE9B,uEAAuE;QACvE,MAAM,UAAU,GAAgC;YAC9C,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC;YAClC,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,CAAC;YACpC,CAAC,SAAS,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC;YACpC,CAAC,SAAS,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC;YACpC,CAAC,SAAS,EAAE,UAAU,CAAC,OAAO,CAAC;SAChC,CAAC;QAEF,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,UAAU,EAAE,CAAC;YACzC,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBACjB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;YACnF,CAAC;QACH,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IACtG,CAAC,CAAC,CAAC;IAEH,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,KAAK,MAAM,IAAI,IAAI,GAAG;QAAE,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;IAE9E,OAAO;QACL,MAAM;QACN,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC;QAC3D,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC;QAC7D,GAAG;KACJ,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,UAAsB;IACjD,OAAO,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;AACzD,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registers a remote MCP server's tools as WebMCP tools on the page.
|
|
3
|
+
*
|
|
4
|
+
* Each registered tool proxies to the connected client's `tools/call` and maps
|
|
5
|
+
* the result back to a WebMCP response, so the agent sees one unified toolset
|
|
6
|
+
* and treats remote and on-page tools alike.
|
|
7
|
+
*
|
|
8
|
+
* Remote schemas are often deeply nested, which small on-device models fill
|
|
9
|
+
* unreliably. Known read tools are therefore registered with a flattened schema
|
|
10
|
+
* that is expanded back to the server's shape before the call. Tools without a
|
|
11
|
+
* mapping keep their native schema.
|
|
12
|
+
*
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
import type { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
16
|
+
import type { McpServerInfo, ModelContext } from '../../types.js';
|
|
17
|
+
/**
|
|
18
|
+
* Convert one `{path: value}` entry into the server's filter object.
|
|
19
|
+
*
|
|
20
|
+
* Numeric values are coerced, since the comparison operators are numeric on the
|
|
21
|
+
* server while a model writes them inside a string.
|
|
22
|
+
*/
|
|
23
|
+
export declare function toFieldFilter(path: string, value: unknown): Record<string, unknown>;
|
|
24
|
+
/**
|
|
25
|
+
* Parse a filter object however the model expressed it.
|
|
26
|
+
*
|
|
27
|
+
* Asked for `{"path": "value"}`, models produce a real object, a JSON string,
|
|
28
|
+
* or a JavaScript-like string with unquoted keys. All three mean the same
|
|
29
|
+
* thing, and rejecting any of them would silently drop the constraint and
|
|
30
|
+
* return unfiltered results.
|
|
31
|
+
*
|
|
32
|
+
* @param raw - The value the model supplied.
|
|
33
|
+
* @returns The parsed object, or null when there is nothing to read.
|
|
34
|
+
*/
|
|
35
|
+
export declare function parseLooseObject(input: unknown): Record<string, unknown> | null;
|
|
36
|
+
/**
|
|
37
|
+
* Flatten a nested filter object into the dot-paths the schema asks for.
|
|
38
|
+
*
|
|
39
|
+
* Models mirror the shape of the data they saw in the last response, which is
|
|
40
|
+
* nested, so `{aggregateRating: {ratingValue: ">=4.5"}}` becomes
|
|
41
|
+
* `{"aggregateRating.ratingValue": ">=4.5"}`.
|
|
42
|
+
*/
|
|
43
|
+
export declare function flattenPaths(obj: Record<string, unknown>, prefix?: string, out?: Record<string, unknown>): Record<string, unknown>;
|
|
44
|
+
/** The model's flat arguments, as the server's nested query. */
|
|
45
|
+
export declare function mapQueryArgs(i: Record<string, unknown>): Record<string, unknown>;
|
|
46
|
+
/** Options for {@link registerRemoteTools}. */
|
|
47
|
+
export interface BridgeOptions {
|
|
48
|
+
/**
|
|
49
|
+
* Choose which of the server's tools reach the page.
|
|
50
|
+
*
|
|
51
|
+
* Rarely needed: the default excludes only {@link SERVER_ONLY_TOOLS}.
|
|
52
|
+
*
|
|
53
|
+
* @param name - The remote tool's name.
|
|
54
|
+
* @returns True to register it.
|
|
55
|
+
*/
|
|
56
|
+
accept?(name: string): boolean;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Register every accepted remote tool into a model context.
|
|
60
|
+
*
|
|
61
|
+
* Each registered tool proxies execution to `client`, translating arguments
|
|
62
|
+
* from the flattened schema and the result back into a WebMCP response.
|
|
63
|
+
*
|
|
64
|
+
* @param client - The connected MCP client.
|
|
65
|
+
* @param mc - The registry to register into.
|
|
66
|
+
* @param info - The server's connection details.
|
|
67
|
+
* @param options - A tool filter.
|
|
68
|
+
* @returns The names of the tools registered.
|
|
69
|
+
*/
|
|
70
|
+
export declare function registerRemoteTools(client: Client, mc: ModelContext, info: McpServerInfo, opts?: BridgeOptions): Promise<string[]>;
|
|
71
|
+
//# sourceMappingURL=bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../../src/harness/tools/bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACxE,OAAO,KAAK,EAEV,aAAa,EACb,YAAY,EAEb,MAAM,gBAAgB,CAAC;AAoGxB;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiBnF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAmC/E;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,MAAM,SAAK,EACX,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUzB;AAED,gEAAgE;AAChE,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAwBhF;AA6CD,+CAA+C;AAC/C,MAAM,WAAW,aAAa;IAC5B;;;;;;;OAOG;IACH,MAAM,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CAChC;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,YAAY,EAChB,IAAI,EAAE,aAAa,EACnB,IAAI,GAAE,aAAkB,GACvB,OAAO,CAAC,MAAM,EAAE,CAAC,CA8BnB"}
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
const isSet = (v) => v != null && String(v).trim() !== '';
|
|
2
|
+
/** Simplified surfaces for the public typed-retrieval tools. */
|
|
3
|
+
const TOOL_OVERRIDES = {
|
|
4
|
+
nxis_list_types: {
|
|
5
|
+
description: "Lists the schema.org types present in this site's data (with counts). Call this first to discover what to query.",
|
|
6
|
+
inputSchema: { type: 'object', properties: {} },
|
|
7
|
+
mapArgs: () => ({}),
|
|
8
|
+
readOnly: true,
|
|
9
|
+
},
|
|
10
|
+
nxis_get: {
|
|
11
|
+
description: 'Fetches one entity by its JSON-LD @id (as returned by nxis_query). Returns the full record.',
|
|
12
|
+
inputSchema: {
|
|
13
|
+
type: 'object',
|
|
14
|
+
properties: {
|
|
15
|
+
id: { type: 'string', description: 'The JSON-LD @id of the entity to fetch.' },
|
|
16
|
+
},
|
|
17
|
+
required: ['id'],
|
|
18
|
+
},
|
|
19
|
+
mapArgs: (i) => ({ id: i.id }),
|
|
20
|
+
readOnly: true,
|
|
21
|
+
},
|
|
22
|
+
nxis_query: {
|
|
23
|
+
description: "Searches the site's typed records by schema.org type, with optional natural-language text " +
|
|
24
|
+
'(use it for locations or keywords), numeric or exact filters on any field, and sorting. ' +
|
|
25
|
+
'Call nxis_list_types first to pick a valid type.',
|
|
26
|
+
inputSchema: {
|
|
27
|
+
type: 'object',
|
|
28
|
+
properties: {
|
|
29
|
+
schema_type: {
|
|
30
|
+
type: 'string',
|
|
31
|
+
description: "schema.org type to search, e.g. 'Electrician', 'LocalBusiness', 'Product'.",
|
|
32
|
+
},
|
|
33
|
+
text: {
|
|
34
|
+
type: 'string',
|
|
35
|
+
// Deliberately generic: this text reaches the model on every site
|
|
36
|
+
// that installs the package, so a concrete example from one
|
|
37
|
+
// deployment would bias the rest.
|
|
38
|
+
description: 'Optional natural-language query — keywords and/or a location.',
|
|
39
|
+
},
|
|
40
|
+
filters: {
|
|
41
|
+
type: 'object',
|
|
42
|
+
// The server takes an array of {path, operator, value} objects,
|
|
43
|
+
// three nested decisions per constraint. A flat object with the
|
|
44
|
+
// comparison written into the value is a shape a small model can
|
|
45
|
+
// reliably produce; it is expanded before the call.
|
|
46
|
+
description: 'Optional exact or numeric filters, as {field path: value}. ' +
|
|
47
|
+
'Prefix a number with >=, >, <= or < to compare, e.g. ' +
|
|
48
|
+
'{"aggregateRating.ratingValue": ">=4.5"}. A plain value matches exactly, ' +
|
|
49
|
+
'and a list matches any of its entries.',
|
|
50
|
+
},
|
|
51
|
+
sort: {
|
|
52
|
+
type: 'string',
|
|
53
|
+
description: 'Optional field path to sort by. Prefix with "-" for highest first, e.g. ' +
|
|
54
|
+
'"-aggregateRating.ratingValue".',
|
|
55
|
+
},
|
|
56
|
+
limit: { type: 'integer', description: 'Maximum results to return (1-100).', default: 10 },
|
|
57
|
+
},
|
|
58
|
+
required: ['schema_type'],
|
|
59
|
+
},
|
|
60
|
+
mapArgs: (i) => mapQueryArgs(i),
|
|
61
|
+
readOnly: true,
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
/** Comparison prefixes the model may write into a filter value. */
|
|
65
|
+
const COMPARISONS = [
|
|
66
|
+
['>=', 'GREATER_THAN_OR_EQUAL'],
|
|
67
|
+
['<=', 'LESS_THAN_OR_EQUAL'],
|
|
68
|
+
['>', 'GREATER_THAN'],
|
|
69
|
+
['<', 'LESS_THAN'],
|
|
70
|
+
];
|
|
71
|
+
/**
|
|
72
|
+
* Convert one `{path: value}` entry into the server's filter object.
|
|
73
|
+
*
|
|
74
|
+
* Numeric values are coerced, since the comparison operators are numeric on the
|
|
75
|
+
* server while a model writes them inside a string.
|
|
76
|
+
*/
|
|
77
|
+
export function toFieldFilter(path, value) {
|
|
78
|
+
if (Array.isArray(value))
|
|
79
|
+
return { path, operator: 'IN', value };
|
|
80
|
+
if (typeof value === 'string') {
|
|
81
|
+
const trimmed = value.trim();
|
|
82
|
+
for (const [prefix, operator] of COMPARISONS) {
|
|
83
|
+
if (trimmed.startsWith(prefix)) {
|
|
84
|
+
const rest = trimmed.slice(prefix.length).trim();
|
|
85
|
+
const num = Number(rest);
|
|
86
|
+
return { path, operator, value: Number.isFinite(num) ? num : rest };
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const num = Number(trimmed);
|
|
90
|
+
// An equality written as "4.5" means the number: a string would not match
|
|
91
|
+
// a numeric field.
|
|
92
|
+
return { path, operator: 'EQUALS', value: trimmed !== '' && Number.isFinite(num) ? num : trimmed };
|
|
93
|
+
}
|
|
94
|
+
return { path, operator: 'EQUALS', value };
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Parse a filter object however the model expressed it.
|
|
98
|
+
*
|
|
99
|
+
* Asked for `{"path": "value"}`, models produce a real object, a JSON string,
|
|
100
|
+
* or a JavaScript-like string with unquoted keys. All three mean the same
|
|
101
|
+
* thing, and rejecting any of them would silently drop the constraint and
|
|
102
|
+
* return unfiltered results.
|
|
103
|
+
*
|
|
104
|
+
* @param raw - The value the model supplied.
|
|
105
|
+
* @returns The parsed object, or null when there is nothing to read.
|
|
106
|
+
*/
|
|
107
|
+
export function parseLooseObject(input) {
|
|
108
|
+
if (input && typeof input === 'object' && !Array.isArray(input)) {
|
|
109
|
+
return input;
|
|
110
|
+
}
|
|
111
|
+
if (typeof input !== 'string')
|
|
112
|
+
return null;
|
|
113
|
+
const text = input.trim();
|
|
114
|
+
if (!text)
|
|
115
|
+
return null;
|
|
116
|
+
// `path >= value`, written with no braces at all.
|
|
117
|
+
const bare = text.match(/^([\w.\-]+)\s*(>=|<=|>|<|=)\s*(.+)$/);
|
|
118
|
+
if (bare && !text.startsWith('{')) {
|
|
119
|
+
const [, path, op, value] = bare;
|
|
120
|
+
return { [path]: op === '=' ? value.trim() : `${op}${value.trim()}` };
|
|
121
|
+
}
|
|
122
|
+
if (!text.startsWith('{'))
|
|
123
|
+
return null;
|
|
124
|
+
const attempts = [
|
|
125
|
+
text,
|
|
126
|
+
// Quote bare keys, and normalise single quotes to double.
|
|
127
|
+
text.replace(/([{,]\s*)([A-Za-z_][\w.\-]*)\s*:/g, '$1"$2":').replace(/'/g, '"'),
|
|
128
|
+
];
|
|
129
|
+
// Last resort: quote bare word values too, as in `{brand: Rheem}`.
|
|
130
|
+
attempts.push(attempts[1].replace(/:\s*([A-Za-z_][\w .\-]*?)\s*([,}])/g, ': "$1"$2'));
|
|
131
|
+
for (const attempt of attempts) {
|
|
132
|
+
try {
|
|
133
|
+
const parsed = JSON.parse(attempt);
|
|
134
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
135
|
+
return parsed;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
/* try the next shape */
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Flatten a nested filter object into the dot-paths the schema asks for.
|
|
146
|
+
*
|
|
147
|
+
* Models mirror the shape of the data they saw in the last response, which is
|
|
148
|
+
* nested, so `{aggregateRating: {ratingValue: ">=4.5"}}` becomes
|
|
149
|
+
* `{"aggregateRating.ratingValue": ">=4.5"}`.
|
|
150
|
+
*/
|
|
151
|
+
export function flattenPaths(obj, prefix = '', out = {}) {
|
|
152
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
153
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
154
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
155
|
+
flattenPaths(value, path, out);
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
out[path] = value;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return out;
|
|
162
|
+
}
|
|
163
|
+
/** The model's flat arguments, as the server's nested query. */
|
|
164
|
+
export function mapQueryArgs(i) {
|
|
165
|
+
const filter = { schema_type: i.schema_type };
|
|
166
|
+
const filters = parseLooseObject(i.filters);
|
|
167
|
+
if (filters) {
|
|
168
|
+
const fieldFilters = Object.entries(flattenPaths(filters))
|
|
169
|
+
.filter(([path, value]) => path && value !== undefined && value !== null && value !== '')
|
|
170
|
+
.map(([path, value]) => toFieldFilter(path, value));
|
|
171
|
+
if (fieldFilters.length)
|
|
172
|
+
filter.field_filters = fieldFilters;
|
|
173
|
+
}
|
|
174
|
+
if (isSet(i.sort)) {
|
|
175
|
+
const raw = String(i.sort).trim();
|
|
176
|
+
const descending = raw.startsWith('-');
|
|
177
|
+
filter.sort_option = {
|
|
178
|
+
property: descending ? raw.slice(1) : raw,
|
|
179
|
+
order: descending ? 'DESCENDING' : 'ASCENDING',
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
const args = { filter };
|
|
183
|
+
if (isSet(i.text))
|
|
184
|
+
args.text = i.text;
|
|
185
|
+
if (i.limit != null)
|
|
186
|
+
args.limit = i.limit;
|
|
187
|
+
return args;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Whether a tool may run without a confirmation step.
|
|
191
|
+
*
|
|
192
|
+
* Fails closed: a tool whose server declares no `readOnlyHint` is treated as a
|
|
193
|
+
* write. The harness runs reads as soon as their arguments are satisfied, so
|
|
194
|
+
* defaulting an unannotated tool to read-only would fire it unattended. Being
|
|
195
|
+
* wrong this way costs one extra confirmation; being wrong the other way sends
|
|
196
|
+
* data on the user's behalf.
|
|
197
|
+
*/
|
|
198
|
+
function isReadOnly(tool, override) {
|
|
199
|
+
if (override)
|
|
200
|
+
return override.readOnly;
|
|
201
|
+
const declared = tool.annotations?.readOnlyHint;
|
|
202
|
+
return declared === true;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* List the server's tools, falling back to the tools its card advertises when
|
|
206
|
+
* `tools/list` is unavailable.
|
|
207
|
+
*/
|
|
208
|
+
async function listRemoteTools(client, info) {
|
|
209
|
+
try {
|
|
210
|
+
const res = await client.listTools();
|
|
211
|
+
return res.tools;
|
|
212
|
+
}
|
|
213
|
+
catch (err) {
|
|
214
|
+
console.warn('[nxis-mcp] tools/list failed; falling back to card publicTools', err);
|
|
215
|
+
return info.publicTools.map((name) => ({ name }));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Tools excluded from the browser agent's toolset by default.
|
|
220
|
+
*
|
|
221
|
+
* `nxis_action` performs a site's write actions server-side, addressed by
|
|
222
|
+
* JSON-LD `@id` and authenticated with an API key. That suits an external MCP
|
|
223
|
+
* client, which has a key and no page, but duplicates the page's own action
|
|
224
|
+
* tools, which are generated from the same Schema.org actions and can show the
|
|
225
|
+
* user what is about to be submitted. Bridging both would offer two routes to
|
|
226
|
+
* the same outcome, and add the excluded tool's schema to every prompt.
|
|
227
|
+
*
|
|
228
|
+
* Override with {@link BridgeOptions.accept}.
|
|
229
|
+
*/
|
|
230
|
+
const SERVER_ONLY_TOOLS = new Set(['nxis_action']);
|
|
231
|
+
/**
|
|
232
|
+
* Register every accepted remote tool into a model context.
|
|
233
|
+
*
|
|
234
|
+
* Each registered tool proxies execution to `client`, translating arguments
|
|
235
|
+
* from the flattened schema and the result back into a WebMCP response.
|
|
236
|
+
*
|
|
237
|
+
* @param client - The connected MCP client.
|
|
238
|
+
* @param mc - The registry to register into.
|
|
239
|
+
* @param info - The server's connection details.
|
|
240
|
+
* @param options - A tool filter.
|
|
241
|
+
* @returns The names of the tools registered.
|
|
242
|
+
*/
|
|
243
|
+
export async function registerRemoteTools(client, mc, info, opts = {}) {
|
|
244
|
+
const accept = opts.accept ?? ((name) => !SERVER_ONLY_TOOLS.has(name));
|
|
245
|
+
const tools = (await listRemoteTools(client, info)).filter((t) => accept(t.name));
|
|
246
|
+
const registered = [];
|
|
247
|
+
for (const tool of tools) {
|
|
248
|
+
const override = TOOL_OVERRIDES[tool.name];
|
|
249
|
+
mc.registerTool({
|
|
250
|
+
name: tool.name,
|
|
251
|
+
description: override?.description ?? tool.description ?? '',
|
|
252
|
+
// Prefer the simplified schema; otherwise pass the native one through.
|
|
253
|
+
inputSchema: override?.inputSchema ?? tool.inputSchema ?? { type: 'object' },
|
|
254
|
+
// The harness reads this to decide whether to run the tool outright, so
|
|
255
|
+
// it must not be optimistic. See isReadOnly.
|
|
256
|
+
annotations: { ...(tool.annotations ?? {}), readOnlyHint: isReadOnly(tool, override) },
|
|
257
|
+
execute: async (input) => {
|
|
258
|
+
const args = override ? override.mapArgs(input ?? {}) : (input ?? {});
|
|
259
|
+
const result = await client.callTool({ name: tool.name, arguments: args });
|
|
260
|
+
return {
|
|
261
|
+
content: result.content ?? [],
|
|
262
|
+
isError: result.isError,
|
|
263
|
+
structuredContent: result.structuredContent,
|
|
264
|
+
};
|
|
265
|
+
},
|
|
266
|
+
});
|
|
267
|
+
registered.push(tool.name);
|
|
268
|
+
}
|
|
269
|
+
return registered;
|
|
270
|
+
}
|
|
271
|
+
//# sourceMappingURL=bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../../src/harness/tools/bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connects an MCP client to a discovered server over Streamable HTTP.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
7
|
+
import type { McpServerInfo } from '../../types.js';
|
|
8
|
+
/** Open an initialized MCP session to `info.endpoint`. Pass `apiKey` only for
|
|
9
|
+
* private tools. Public typed retrieval needs no credential. */
|
|
10
|
+
export declare function connectMcp(info: McpServerInfo, apiKey?: string): Promise<Client>;
|
|
11
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/harness/tools/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAEnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD;gEACgE;AAChE,wBAAsB,UAAU,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CActF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connects an MCP client to a discovered server over Streamable HTTP.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
7
|
+
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
|
|
8
|
+
/** Open an initialized MCP session to `info.endpoint`. Pass `apiKey` only for
|
|
9
|
+
* private tools. Public typed retrieval needs no credential. */
|
|
10
|
+
export async function connectMcp(info, apiKey) {
|
|
11
|
+
const headers = {};
|
|
12
|
+
if (apiKey && info.authHeaderName)
|
|
13
|
+
headers[info.authHeaderName] = apiKey;
|
|
14
|
+
const transport = new StreamableHTTPClientTransport(new URL(info.endpoint), {
|
|
15
|
+
requestInit: { headers },
|
|
16
|
+
});
|
|
17
|
+
const client = new Client({ name: 'nxisai-browser-agent', version: '1.0.0' }, { capabilities: {} });
|
|
18
|
+
await client.connect(transport);
|
|
19
|
+
return client;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/harness/tools/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AAGnG;gEACgE;AAChE,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAmB,EAAE,MAAe;IACnE,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,IAAI,MAAM,IAAI,IAAI,CAAC,cAAc;QAAE,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,MAAM,CAAC;IAEzE,MAAM,SAAS,GAAG,IAAI,6BAA6B,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;QAC1E,WAAW,EAAE,EAAE,OAAO,EAAE;KACzB,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,OAAO,EAAE,EAClD,EAAE,YAAY,EAAE,EAAE,EAAE,CACrB,CAAC;IACF,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,MAAM,CAAC;AAChB,CAAC"}
|