@rarebit-one/harness-kernel 0.15.0 → 0.19.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 +268 -17
- package/dist/agent.d.ts +24 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +138 -30
- package/dist/agent.js.map +1 -1
- package/dist/connectors/auth.d.ts +32 -0
- package/dist/connectors/auth.d.ts.map +1 -0
- package/dist/connectors/auth.js +85 -0
- package/dist/connectors/auth.js.map +1 -0
- package/dist/connectors/mcpClient.d.ts +14 -4
- package/dist/connectors/mcpClient.d.ts.map +1 -1
- package/dist/connectors/mcpClient.js +32 -11
- package/dist/connectors/mcpClient.js.map +1 -1
- package/dist/engines/acp.d.ts.map +1 -1
- package/dist/engines/acp.js +2 -1
- package/dist/engines/acp.js.map +1 -1
- package/dist/engines/agentSdk.d.ts +11 -0
- package/dist/engines/agentSdk.d.ts.map +1 -0
- package/dist/engines/agentSdk.js +26 -0
- package/dist/engines/agentSdk.js.map +1 -0
- package/dist/engines/agentSdkMissing.d.ts +6 -0
- package/dist/engines/agentSdkMissing.d.ts.map +1 -0
- package/dist/engines/agentSdkMissing.js +12 -0
- package/dist/engines/agentSdkMissing.js.map +1 -0
- package/dist/engines/capability.d.ts +1 -1
- package/dist/engines/capability.js +1 -1
- package/dist/engines/capabilityMcp.d.ts +14 -4
- package/dist/engines/capabilityMcp.d.ts.map +1 -1
- package/dist/engines/capabilityMcp.js +5 -3
- package/dist/engines/capabilityMcp.js.map +1 -1
- package/dist/engines/claudeCode.d.ts.map +1 -1
- package/dist/engines/claudeCode.js +2 -1
- package/dist/engines/claudeCode.js.map +1 -1
- package/dist/engines/claudeCodeDriver.d.ts +4 -3
- package/dist/engines/claudeCodeDriver.d.ts.map +1 -1
- package/dist/engines/claudeCodeDriver.js +13 -8
- package/dist/engines/claudeCodeDriver.js.map +1 -1
- package/dist/engines/codex.d.ts +4 -4
- package/dist/engines/codex.d.ts.map +1 -1
- package/dist/engines/codex.js +6 -5
- package/dist/engines/codex.js.map +1 -1
- package/dist/engines/codexDriver.d.ts +1 -1
- package/dist/engines/codexDriver.js +1 -1
- package/dist/engines/connectorMcp.d.ts +13 -0
- package/dist/engines/connectorMcp.d.ts.map +1 -1
- package/dist/engines/connectorMcp.js +23 -0
- package/dist/engines/connectorMcp.js.map +1 -1
- package/dist/engines/gateway.d.ts +5 -2
- package/dist/engines/gateway.d.ts.map +1 -1
- package/dist/engines/gateway.js +7 -2
- package/dist/engines/gateway.js.map +1 -1
- package/dist/engines/native.d.ts.map +1 -1
- package/dist/engines/native.js +10 -3
- package/dist/engines/native.js.map +1 -1
- package/dist/engines/types.d.ts +10 -1
- package/dist/engines/types.d.ts.map +1 -1
- package/dist/events.d.ts +22 -8
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js.map +1 -1
- package/dist/index.d.ts +14 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -2
- package/dist/index.js.map +1 -1
- package/dist/loop.d.ts +23 -0
- package/dist/loop.d.ts.map +1 -1
- package/dist/loop.js +1 -0
- package/dist/loop.js.map +1 -1
- package/dist/models/chat.d.ts +12 -6
- package/dist/models/chat.d.ts.map +1 -1
- package/dist/models/chat.js +11 -6
- package/dist/models/chat.js.map +1 -1
- package/dist/models/retry.d.ts +252 -0
- package/dist/models/retry.d.ts.map +1 -0
- package/dist/models/retry.js +400 -0
- package/dist/models/retry.js.map +1 -0
- package/dist/models/types.d.ts +7 -0
- package/dist/models/types.d.ts.map +1 -1
- package/dist/models/types.js.map +1 -1
- package/dist/private.d.ts.map +1 -1
- package/dist/private.js +12 -2
- package/dist/private.js.map +1 -1
- package/dist/providers/anthropic.d.ts +1 -2
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +0 -12
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/mock.d.ts +1 -2
- package/dist/providers/mock.d.ts.map +1 -1
- package/dist/providers/mock.js +14 -18
- package/dist/providers/mock.js.map +1 -1
- package/dist/providers/openai.d.ts +1 -2
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +0 -14
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/scripted.d.ts +1 -3
- package/dist/providers/scripted.d.ts.map +1 -1
- package/dist/providers/scripted.js +0 -9
- package/dist/providers/scripted.js.map +1 -1
- package/dist/providers/types.d.ts +0 -6
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/secrets.d.ts +17 -7
- package/dist/secrets.d.ts.map +1 -1
- package/dist/secrets.js +38 -24
- package/dist/secrets.js.map +1 -1
- package/dist/tools/concurrency.d.ts +48 -0
- package/dist/tools/concurrency.d.ts.map +1 -0
- package/dist/tools/concurrency.js +64 -0
- package/dist/tools/concurrency.js.map +1 -0
- package/dist/tools/metadata.d.ts +18 -3
- package/dist/tools/metadata.d.ts.map +1 -1
- package/dist/tools/metadata.js +7 -0
- package/dist/tools/metadata.js.map +1 -1
- package/dist/tools/registry.d.ts +6 -4
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +5 -3
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/terminal.d.ts +8 -6
- package/dist/tools/terminal.d.ts.map +1 -1
- package/dist/tools/terminal.js +8 -6
- package/dist/tools/terminal.js.map +1 -1
- package/dist/tools/validate.d.ts +49 -0
- package/dist/tools/validate.d.ts.map +1 -0
- package/dist/tools/validate.js +346 -0
- package/dist/tools/validate.js.map +1 -0
- package/dist/transcript.d.ts +53 -0
- package/dist/transcript.d.ts.map +1 -0
- package/dist/transcript.js +104 -0
- package/dist/transcript.js.map +1 -0
- package/dist/types.d.ts +44 -5
- package/dist/types.d.ts.map +1 -1
- package/package.json +13 -5
package/dist/tools/metadata.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ import type { Tool } from "./registry.js";
|
|
|
11
11
|
*
|
|
12
12
|
* The metadata here is only ever *descriptive*. The kernel records that a tool
|
|
13
13
|
* says `requiresConfirmation`; it never implements a confirmation flow, because
|
|
14
|
-
* what confirmation means — a modal, a
|
|
14
|
+
* what confirmation means — a modal, a chat approval, a second agent — is the
|
|
15
15
|
* application's decision. Same for undo and retention. Policy lives in the app
|
|
16
16
|
* layer; the vocabulary lives here so every layer agrees on the words.
|
|
17
17
|
*/
|
|
@@ -33,8 +33,9 @@ export type ResultRetention = "ephemeral" | "standard" | "persistent";
|
|
|
33
33
|
* - `terminal` — run it, append its result, then END the loop with the call
|
|
34
34
|
* as the structured answer. A final-answer tool. The other
|
|
35
35
|
* calls of the same assistant turn still run (in order), so
|
|
36
|
-
* the transcript stays whole; the first terminal call
|
|
37
|
-
* succeeds is the answer
|
|
36
|
+
* the transcript stays whole; the first terminal call, in the
|
|
37
|
+
* model's order, that succeeds is the answer, even when calls
|
|
38
|
+
* ran in parallel and a later one finished first.
|
|
38
39
|
* - `external` — the loop does not run it: the call is parked on
|
|
39
40
|
* `LoopResult.pending`, the run ends `suspended`, and the
|
|
40
41
|
* caller resumes the conversation with the call's result (or
|
|
@@ -93,6 +94,15 @@ export interface ToolMetadata {
|
|
|
93
94
|
* kernel only records the claim; deciding to replay is the application's.
|
|
94
95
|
*/
|
|
95
96
|
replay?: "safe" | "unsafe";
|
|
97
|
+
/**
|
|
98
|
+
* The tool may run at the same time as other calls of the same step: it has
|
|
99
|
+
* no effect another call could observe or race (a read, a lookup). Absent
|
|
100
|
+
* means it makes no such claim, and it runs alone. The loop never reads this
|
|
101
|
+
* itself; a run that opts into parallel calls passes a predicate
|
|
102
|
+
* (`toolConcurrency.concurrencySafe`), and `isConcurrencySafe` honours this
|
|
103
|
+
* field.
|
|
104
|
+
*/
|
|
105
|
+
concurrencySafe?: boolean;
|
|
96
106
|
resultRetention?: ResultRetention;
|
|
97
107
|
clientResultVisibility?: ClientResultVisibility;
|
|
98
108
|
}
|
|
@@ -130,6 +140,11 @@ export declare function toolsRequiringConfirmation(tools: Tool[]): Tool[];
|
|
|
130
140
|
* after an interruption. An undeclared tool is excluded: absent means unsafe.
|
|
131
141
|
*/
|
|
132
142
|
export declare function replaySafeTools(tools: Tool[]): Tool[];
|
|
143
|
+
/**
|
|
144
|
+
* Whether a tool declared `concurrencySafe: true`. The predicate to pass as
|
|
145
|
+
* `toolConcurrency.concurrencySafe` when the tools' own claims are the policy.
|
|
146
|
+
*/
|
|
147
|
+
export declare function isConcurrencySafe(tool: Tool): boolean;
|
|
133
148
|
/** Look up the tool that undoes `name`, when one is declared and reversible. */
|
|
134
149
|
export declare function undoToolFor(tools: Tool[], name: string): Tool | undefined;
|
|
135
150
|
//# sourceMappingURL=metadata.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/tools/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AAEzC;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GAAG,gBAAgB,GAAG,kBAAkB,CAAA;AAElE,iEAAiE;AACjE,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,UAAU,GAAG,YAAY,CAAA;AAErE
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/tools/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AAEzC;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GAAG,gBAAgB,GAAG,kBAAkB,CAAA;AAElE,iEAAiE;AACjE,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,UAAU,GAAG,YAAY,CAAA;AAErE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAA;AAE9D;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,YAAY,CAAA;AAE1D;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,YAAY,CAAA;IACvB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;IACpC;;;;;OAKG;IACH,eAAe,CAAC,EAAE,cAAc,EAAE,GAAG,IAAI,CAAA;IACzC,+DAA+D;IAC/D,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,gCAAgC;IAChC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,wDAAwD;IACxD,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,qCAAqC;IACrC,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAA;IAC1B;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,sBAAsB,CAAC,EAAE,sBAAsB,CAAA;CAChD;AAED,sDAAsD;AACtD,MAAM,WAAW,aAAa;IAC5B,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,sEAAsE;IACtE,IAAI,CAAC,EAAE,cAAc,CAAA;IACrB,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CACnB;AAED,qDAAqD;AACrD,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,GAAE,aAAkB,GAAG,OAAO,CAmBhF;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,SAAS,GAAE,aAAkB,GAAG,IAAI,EAAE,CAEhF;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,QAAQ,EAAE,CAErD;AAED,mDAAmD;AACnD,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,YAAY,CAErD;AAED,+DAA+D;AAC/D,wBAAgB,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,CAEnD;AAED,mEAAmE;AACnE,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,CAEhE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,CAErD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAErD;AAED,gFAAgF;AAChF,wBAAgB,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAIzE"}
|
package/dist/tools/metadata.js
CHANGED
|
@@ -54,6 +54,13 @@ export function toolsRequiringConfirmation(tools) {
|
|
|
54
54
|
export function replaySafeTools(tools) {
|
|
55
55
|
return tools.filter((tool) => tool.meta?.replay === "safe");
|
|
56
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Whether a tool declared `concurrencySafe: true`. The predicate to pass as
|
|
59
|
+
* `toolConcurrency.concurrencySafe` when the tools' own claims are the policy.
|
|
60
|
+
*/
|
|
61
|
+
export function isConcurrencySafe(tool) {
|
|
62
|
+
return tool.meta?.concurrencySafe === true;
|
|
63
|
+
}
|
|
57
64
|
/** Look up the tool that undoes `name`, when one is declared and reversible. */
|
|
58
65
|
export function undoToolFor(tools, name) {
|
|
59
66
|
const tool = tools.find((t) => t.spec.name === name);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/tools/metadata.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/tools/metadata.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/registry.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type McpConnection } from "../connectors/mcpClient.js";
|
|
1
|
+
import { type ConnectMcpOptions, type McpConnection } from "../connectors/mcpClient.js";
|
|
2
2
|
import type { ConnectorConfig } from "../types.js";
|
|
3
3
|
import type { ToolSpec } from "../providers/types.js";
|
|
4
4
|
import type { ToolMetadata } from "./metadata.js";
|
|
@@ -79,12 +79,14 @@ export declare const namespacedToolName: ConnectorToolName;
|
|
|
79
79
|
* `<connector>__<tool>` by default so two connectors cannot collide; pass
|
|
80
80
|
* `toolName` to name them differently (a single-connector application may
|
|
81
81
|
* want the server's own names, so its prompts and its tool names match).
|
|
82
|
-
* Returns a `close` to tear down the connections when the run ends.
|
|
82
|
+
* Returns a `close` to tear down the connections when the run ends. `onSecret`
|
|
83
|
+
* is handed to `connect` and hears every connector credential, including each
|
|
84
|
+
* rotated one an `auth.headers` function returns mid-run.
|
|
83
85
|
*/
|
|
84
|
-
export declare function connectorTools(connectors: ConnectorConfig[], connect?: (config: ConnectorConfig) => Promise<McpConnection>, opts?: {
|
|
86
|
+
export declare function connectorTools(connectors: ConnectorConfig[], connect?: (config: ConnectorConfig, opts?: ConnectMcpOptions) => Promise<McpConnection>, opts?: {
|
|
85
87
|
signal?: AbortSignal;
|
|
86
88
|
toolName?: ConnectorToolName;
|
|
87
|
-
}): Promise<{
|
|
89
|
+
} & ConnectMcpOptions): Promise<{
|
|
88
90
|
tools: Tool[];
|
|
89
91
|
close: () => Promise<void>;
|
|
90
92
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"AAGA,OAAO,EAAc,KAAK,aAAa,EAAE,MAAM,4BAA4B,CAAA;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"AAGA,OAAO,EAAc,KAAK,iBAAiB,EAAE,KAAK,aAAa,EAAE,MAAM,4BAA4B,CAAA;AACnG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAEjD;;;;;;;;GAQG;AACH,MAAM,WAAW,UAAU;IACzB,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAA;IACf,4DAA4D;IAC5D,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,WAAW,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,8EAA8E;AAC9E,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,QAAQ,CAAA;IACd,8EAA8E;IAC9E,IAAI,CAAC,EAAE,YAAY,CAAA;IACnB;;;OAGG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAC3E;;;;;;;;OAQG;IACH,iBAAiB,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;CAC3F;AAED,sFAAsF;AACtF,wBAAsB,WAAW,CAC/B,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,GAAG,CAAC,EAAE,WAAW,GAChB,OAAO,CAAC,UAAU,CAAC,CAGrB;AAsCD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,OAAO,CAAC,EAAE,MAAM,EAAE,EAClB,UAAU,CAAC,EAAE,MAAM,EAAE,GACpB,IAAI,EAAE,CAiGR;AAED,gFAAgF;AAChF,MAAM,MAAM,iBAAiB,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAA;AAEnF,4EAA4E;AAC5E,eAAO,MAAM,kBAAkB,EAAE,iBAAgE,CAAA;AAEjG;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,UAAU,EAAE,eAAe,EAAE,EAC7B,OAAO,GAAE,CACP,MAAM,EAAE,eAAe,EACvB,IAAI,CAAC,EAAE,iBAAiB,KACrB,OAAO,CAAC,aAAa,CAAc,EACxC,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,EAAE,iBAAiB,CAAA;CAAE,GAAG,iBAAsB,GACpF,OAAO,CAAC;IAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,CAoExD"}
|
package/dist/tools/registry.js
CHANGED
|
@@ -154,10 +154,12 @@ export const namespacedToolName = (connector, tool) => `${connector}__${tool}`;
|
|
|
154
154
|
* `<connector>__<tool>` by default so two connectors cannot collide; pass
|
|
155
155
|
* `toolName` to name them differently (a single-connector application may
|
|
156
156
|
* want the server's own names, so its prompts and its tool names match).
|
|
157
|
-
* Returns a `close` to tear down the connections when the run ends.
|
|
157
|
+
* Returns a `close` to tear down the connections when the run ends. `onSecret`
|
|
158
|
+
* is handed to `connect` and hears every connector credential, including each
|
|
159
|
+
* rotated one an `auth.headers` function returns mid-run.
|
|
158
160
|
*/
|
|
159
161
|
export async function connectorTools(connectors, connect = connectMcp, opts = {}) {
|
|
160
|
-
const { signal } = opts;
|
|
162
|
+
const { signal, onSecret } = opts;
|
|
161
163
|
const nameFor = opts.toolName ?? namespacedToolName;
|
|
162
164
|
const connections = [];
|
|
163
165
|
// Each setup await stops waiting the moment `signal` aborts, so a stalled
|
|
@@ -182,7 +184,7 @@ export async function connectorTools(connectors, connect = connectMcp, opts = {}
|
|
|
182
184
|
for (const config of connectors) {
|
|
183
185
|
if (config.kind !== "mcp")
|
|
184
186
|
continue;
|
|
185
|
-
const connecting = connect(config);
|
|
187
|
+
const connecting = onSecret ? connect(config, { onSecret }) : connect(config);
|
|
186
188
|
let conn;
|
|
187
189
|
try {
|
|
188
190
|
conn = await step(connecting);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACjD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAoB,MAAM,qBAAqB,CAAA;AAClF,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACjD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAoB,MAAM,qBAAqB,CAAA;AAClF,OAAO,EAAE,UAAU,EAA8C,MAAM,4BAA4B,CAAA;AA6DnG,sFAAsF;AACtF,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAU,EACV,KAA8B,EAC9B,GAAiB;IAEjB,IAAI,IAAI,CAAC,iBAAiB;QAAE,OAAO,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;IACrE,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAA;AACpD,CAAC;AAED,MAAM,GAAG,GAAG,CAAC,CAAU,EAAU,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;AACpE,MAAM,QAAQ,GAAG,CAAC,CAAU,EAAY,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;AAElF,2EAA2E;AAC3E,SAAS,aAAa,CAAC,CAAU;IAC/B,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAA;IACjD,MAAM,GAAG,GAA2B,EAAE,CAAA;IACtC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAA4B,CAAC,EAAE,CAAC;QACxE,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;IACjD,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;GAIG;AACH,SAAS,YAAY,CAAC,IAAY,EAAE,IAAiB;IACnD,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,MAAM;YACT,OAAO,IAAI,CAAC,IAAI,CAAA;QAClB,KAAK,SAAS;YACZ,OAAO,aAAa,CAAA;QACtB,KAAK,WAAW;YACd,OAAO,cAAc,IAAI,kCAAkC,CAAA;QAC7D,KAAK,WAAW;YACd,OAAO,CACL,cAAc,IAAI,OAAO,IAAI,CAAC,KAAK,oBAAoB,IAAI,CAAC,QAAQ,yBAAyB;gBAC7F,iEAAiE,CAClE,CAAA;QACH,KAAK,QAAQ;YACX,OAAO,cAAc,IAAI,wBAAwB,IAAI,CAAC,KAAK,8CAA8C,CAAA;IAC7G,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAC5B,UAAkB,EAClB,GAAsB,EACtB,OAAkB,EAClB,UAAqB;IAErB,MAAM,GAAG,GAAW;QAClB;YACE,IAAI,EAAE;gBACJ,IAAI,EAAE,UAAU;gBAChB,WAAW,EACT,iGAAiG;oBACjG,qGAAqG;oBACrG,oGAAoG;oBACpG,mFAAmF;gBACrF,WAAW,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBAC3B,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;wBAClD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;qBAC1B;oBACD,QAAQ,EAAE,CAAC,SAAS,CAAC;iBACtB;aACF;YACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;gBAC5B,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;gBAClC,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;gBACjC,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAA;gBACvE,wEAAwE;gBACxE,MAAM,MAAM,GAAG,GAAG,EAAE,MAAM,CAAA;gBAC1B,0EAA0E;gBAC1E,4EAA4E;gBAC5E,6EAA6E;gBAC7E,MAAM,MAAM,GACV,IAAI,CAAC,MAAM,GAAG,CAAC;oBACb,CAAC,CAAC,MAAM,OAAO,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;oBACvE,CAAC,CAAC,MAAM,OAAO,CAAC;wBACZ,GAAG,EAAE,UAAU;wBACf,OAAO,EAAE,SAAS;wBAClB,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC;wBACrB,GAAG;wBACH,KAAK;wBACL,MAAM;qBACP,CAAC,CAAA;gBACR,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;YAC/B,CAAC;SACF;QACD;YACE,IAAI,EAAE;gBACJ,IAAI,EAAE,WAAW;gBACjB,WAAW,EAAE,+CAA+C;gBAC5D,WAAW,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;oBACxC,QAAQ,EAAE,CAAC,MAAM,CAAC;iBACnB;aACF;YACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CACvB,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,eAAe,CAAC,UAAU,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;SACpF;QACD;YACE,IAAI,EAAE;gBACJ,IAAI,EAAE,YAAY;gBAClB,WAAW,EAAE,wDAAwD;gBACrE,WAAW,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;iBACxC;aACF;YACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,MAAM,SAAS,CAAC,UAAU,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;SAC1F;QACD;YACE,IAAI,EAAE;gBACJ,IAAI,EAAE,YAAY;gBAClB,WAAW,EAAE,6DAA6D;gBAC1E,WAAW,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBACvB,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBAC1B,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBAC3B,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;qBACzB;oBACD,QAAQ,EAAE,CAAC,KAAK,CAAC;iBAClB;aACF;YACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;gBAC5B,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC;oBAC1B,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;oBACnB,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK;oBAClC,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC;oBACrC,IAAI,EAAE,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;oBAC7D,UAAU,EAAE,iFAAiF;oBAC7F,MAAM,EAAE,GAAG,EAAE,MAAM;iBACpB,CAAC,CAAA;gBACF,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAA;YAC/D,CAAC;SACF;KACF,CAAA;IAED,OAAO,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;AACzE,CAAC;AAKD,4EAA4E;AAC5E,MAAM,CAAC,MAAM,kBAAkB,GAAsB,CAAC,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,SAAS,KAAK,IAAI,EAAE,CAAA;AAEjG;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,UAA6B,EAC7B,UAG8B,UAAU,EACxC,OAAmF,EAAE;IAErF,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAA;IACjC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,IAAI,kBAAkB,CAAA;IACnD,MAAM,WAAW,GAAoB,EAAE,CAAA;IACvC,0EAA0E;IAC1E,uEAAuE;IACvE,2EAA2E;IAC3E,MAAM,IAAI,GAAG,CAAI,IAAgB,EAAc,EAAE;QAC/C,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAA;QACxB,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACxC,MAAM,OAAO,GAAG,GAAS,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,MAAe,CAAC,CAAA;YAC1D,IAAI,MAAM,CAAC,OAAO;gBAAE,OAAO,OAAO,EAAE,CAAA;YACpC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;YACzD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA;QACxF,CAAC,CAAC,CAAA;IACJ,CAAC,CAAA;IACD,MAAM,KAAK,GAAW,EAAE,CAAA;IACxB,MAAM,KAAK,GAAG,KAAK,IAAmB,EAAE;QACtC,MAAM,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IAC7D,CAAC,CAAA;IAED,IAAI,CAAC;QACH,KAAK,MAAM,MAAM,IAAI,UAAU,EAAE,CAAC;YAChC,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK;gBAAE,SAAQ;YAEnC,MAAM,UAAU,GAAG,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;YAC7E,IAAI,IAAmB,CAAA;YACvB,IAAI,CAAC;gBACH,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,CAAA;YAC/B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,KAAK,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;gBAC5D,MAAM,GAAG,CAAA;YACX,CAAC;YACD,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAEtB,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAE3C,CAAA;YAED,wEAAwE;YACxE,0DAA0D;YAC1D,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAA;YAC5B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;gBACtC,IAAI,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;oBAAE,SAAQ;gBACrD,KAAK,CAAC,IAAI,CAAC;oBACT,IAAI,EAAE;wBACJ,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC;wBACrC,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,GAAG,MAAM,CAAC,IAAI,SAAS,IAAI,CAAC,IAAI,EAAE;wBACnE,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE;qBACpD;oBACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;wBAC5B,+DAA+D;wBAC/D,iEAAiE;wBACjE,MAAM,MAAM,GAAG,GAAG;4BAChB,CAAC,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;4BAC/D,CAAC,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;wBACzC,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;oBAC/B,CAAC;iBACF,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,wDAAwD;QACxD,MAAM,KAAK,EAAE,CAAA;QACb,MAAM,GAAG,CAAA;IACX,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;AACzB,CAAC"}
|
package/dist/tools/terminal.d.ts
CHANGED
|
@@ -15,12 +15,14 @@ export interface TerminalToolOptions {
|
|
|
15
15
|
*
|
|
16
16
|
* This is how a conversational application gets a typed reply out of the loop
|
|
17
17
|
* instead of parsing prose. The model is told the schema through the tool
|
|
18
|
-
* definition, so the shape is enforced where models enforce shapes best.
|
|
19
|
-
* kernel does not
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
18
|
+
* definition, so the shape is enforced where models enforce shapes best. By
|
|
19
|
+
* default the kernel does not check the arguments against the schema; a run
|
|
20
|
+
* with `validateToolInput: true` does, and refuses a call that does not fit
|
|
21
|
+
* before it can end the run, telling the model what to fix. A rule the schema
|
|
22
|
+
* cannot express (one field required only when another has a given value) is
|
|
23
|
+
* the caller's: supply your own `Tool` with `meta.dispatch: "terminal"` whose
|
|
24
|
+
* executor throws on a bad answer, which sends the error back to the model and
|
|
25
|
+
* lets it try again.
|
|
24
26
|
*
|
|
25
27
|
* The executor here is a no-op that acknowledges the call: a tool result still
|
|
26
28
|
* has to be appended so the transcript carries no dangling tool call and can be
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../src/tools/terminal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AAEzC,MAAM,WAAW,mBAAmB;IAClC,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,oEAAoE;IACpE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,+DAA+D;IAC/D,IAAI,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,CAAA;CACtC;AAED
|
|
1
|
+
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../src/tools/terminal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AAEzC,MAAM,WAAW,mBAAmB;IAClC,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,oEAAoE;IACpE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,+DAA+D;IAC/D,IAAI,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,CAAA;CACtC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAU/D"}
|
package/dist/tools/terminal.js
CHANGED
|
@@ -4,12 +4,14 @@
|
|
|
4
4
|
*
|
|
5
5
|
* This is how a conversational application gets a typed reply out of the loop
|
|
6
6
|
* instead of parsing prose. The model is told the schema through the tool
|
|
7
|
-
* definition, so the shape is enforced where models enforce shapes best.
|
|
8
|
-
* kernel does not
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
7
|
+
* definition, so the shape is enforced where models enforce shapes best. By
|
|
8
|
+
* default the kernel does not check the arguments against the schema; a run
|
|
9
|
+
* with `validateToolInput: true` does, and refuses a call that does not fit
|
|
10
|
+
* before it can end the run, telling the model what to fix. A rule the schema
|
|
11
|
+
* cannot express (one field required only when another has a given value) is
|
|
12
|
+
* the caller's: supply your own `Tool` with `meta.dispatch: "terminal"` whose
|
|
13
|
+
* executor throws on a bad answer, which sends the error back to the model and
|
|
14
|
+
* lets it try again.
|
|
13
15
|
*
|
|
14
16
|
* The executor here is a no-op that acknowledges the call: a tool result still
|
|
15
17
|
* has to be appended so the transcript carries no dangling tool call and can be
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal.js","sourceRoot":"","sources":["../../src/tools/terminal.ts"],"names":[],"mappings":"AAaA
|
|
1
|
+
{"version":3,"file":"terminal.js","sourceRoot":"","sources":["../../src/tools/terminal.ts"],"names":[],"mappings":"AAaA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,YAAY,CAAC,OAA4B;IACvD,OAAO;QACL,IAAI,EAAE;YACJ,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,WAAW,EAAE,OAAO,CAAC,WAAW;SACjC;QACD,IAAI,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE;QAC/C,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC;KAC3C,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Tool } from "./registry.js";
|
|
2
|
+
/**
|
|
3
|
+
* One way a tool call's arguments fail the tool's declared `inputSchema`.
|
|
4
|
+
* `path` is a JSON Pointer into the arguments (`/items/0/name`), or `""` for
|
|
5
|
+
* the arguments object itself.
|
|
6
|
+
*/
|
|
7
|
+
export interface ToolInputProblem {
|
|
8
|
+
path: string;
|
|
9
|
+
message: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Check a tool call's arguments against a JSON Schema, returning every problem
|
|
13
|
+
* found (empty when the arguments fit).
|
|
14
|
+
*
|
|
15
|
+
* This is the subset of JSON Schema that tool schemas actually use: `type`
|
|
16
|
+
* (including `integer`, `null` and type arrays), `properties`, `required`,
|
|
17
|
+
* `additionalProperties`, `enum`, `const`, `items` / `prefixItems`, the
|
|
18
|
+
* length, size and range bounds, `pattern`, `allOf` / `anyOf` / `oneOf`,
|
|
19
|
+
* local `$ref`s (`#/$defs/...`, `#/definitions/...`) and OpenAPI's
|
|
20
|
+
* `nullable`. A `$ref`'s sibling keywords apply as in 2019-09 and later, and
|
|
21
|
+
* are ignored when the root `$schema` names draft 03 to 07, where a `$ref`
|
|
22
|
+
* replaced its whole schema object; `const` is ignored before draft 6 and
|
|
23
|
+
* `prefixItems` before 2020-12, the drafts that introduced them. Any other keyword (`format`, `not`,
|
|
24
|
+
* `if`/`then`/`else`, `multipleOf`, `uniqueItems`, the `dependent*` family, a
|
|
25
|
+
* remote or malformed `$ref`, a local `$ref` inside an embedded resource with
|
|
26
|
+
* its own `$id`, a `type` name outside the seven JSON types) is ignored, and
|
|
27
|
+
* `oneOf` is read as `anyOf`. A schema whose check would take more than a
|
|
28
|
+
* fixed amount of work is not judged at all: no problems are returned.
|
|
29
|
+
*
|
|
30
|
+
* Ignoring is the point: the validator may let a bad call through, but it
|
|
31
|
+
* never refuses a call the schema accepts. A refusal costs the model a turn,
|
|
32
|
+
* so a false one is worse than a missed one, and a schema written by someone
|
|
33
|
+
* else (an MCP server's) can use any keyword it likes without the run
|
|
34
|
+
* starting to refuse calls its server would have taken.
|
|
35
|
+
*
|
|
36
|
+
* `pattern` is compiled and run synchronously on the model's input, like any
|
|
37
|
+
* regular expression. A schema author's pattern with catastrophic
|
|
38
|
+
* backtracking (`^(a+)+$`) can stall the event loop, and the run's deadline
|
|
39
|
+
* cannot interrupt it; turn validation on only for tools whose schemas you
|
|
40
|
+
* would run that way.
|
|
41
|
+
*/
|
|
42
|
+
export declare function validateToolInput(schema: unknown, input: unknown): ToolInputProblem[];
|
|
43
|
+
/**
|
|
44
|
+
* The tool result a call gets when its arguments fail the tool's schema, or
|
|
45
|
+
* `undefined` when they fit. The loop answers the call with this instead of
|
|
46
|
+
* running it, and the model corrects the call within its own budgets.
|
|
47
|
+
*/
|
|
48
|
+
export declare function invalidInputRefusal(tool: Tool, input: Record<string, unknown>): string | undefined;
|
|
49
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/tools/validate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AAEzC;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,gBAAgB,EAAE,CAUrF;AAKD;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,MAAM,GAAG,SAAS,CAmBpB"}
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check a tool call's arguments against a JSON Schema, returning every problem
|
|
3
|
+
* found (empty when the arguments fit).
|
|
4
|
+
*
|
|
5
|
+
* This is the subset of JSON Schema that tool schemas actually use: `type`
|
|
6
|
+
* (including `integer`, `null` and type arrays), `properties`, `required`,
|
|
7
|
+
* `additionalProperties`, `enum`, `const`, `items` / `prefixItems`, the
|
|
8
|
+
* length, size and range bounds, `pattern`, `allOf` / `anyOf` / `oneOf`,
|
|
9
|
+
* local `$ref`s (`#/$defs/...`, `#/definitions/...`) and OpenAPI's
|
|
10
|
+
* `nullable`. A `$ref`'s sibling keywords apply as in 2019-09 and later, and
|
|
11
|
+
* are ignored when the root `$schema` names draft 03 to 07, where a `$ref`
|
|
12
|
+
* replaced its whole schema object; `const` is ignored before draft 6 and
|
|
13
|
+
* `prefixItems` before 2020-12, the drafts that introduced them. Any other keyword (`format`, `not`,
|
|
14
|
+
* `if`/`then`/`else`, `multipleOf`, `uniqueItems`, the `dependent*` family, a
|
|
15
|
+
* remote or malformed `$ref`, a local `$ref` inside an embedded resource with
|
|
16
|
+
* its own `$id`, a `type` name outside the seven JSON types) is ignored, and
|
|
17
|
+
* `oneOf` is read as `anyOf`. A schema whose check would take more than a
|
|
18
|
+
* fixed amount of work is not judged at all: no problems are returned.
|
|
19
|
+
*
|
|
20
|
+
* Ignoring is the point: the validator may let a bad call through, but it
|
|
21
|
+
* never refuses a call the schema accepts. A refusal costs the model a turn,
|
|
22
|
+
* so a false one is worse than a missed one, and a schema written by someone
|
|
23
|
+
* else (an MCP server's) can use any keyword it likes without the run
|
|
24
|
+
* starting to refuse calls its server would have taken.
|
|
25
|
+
*
|
|
26
|
+
* `pattern` is compiled and run synchronously on the model's input, like any
|
|
27
|
+
* regular expression. A schema author's pattern with catastrophic
|
|
28
|
+
* backtracking (`^(a+)+$`) can stall the event loop, and the run's deadline
|
|
29
|
+
* cannot interrupt it; turn validation on only for tools whose schemas you
|
|
30
|
+
* would run that way.
|
|
31
|
+
*/
|
|
32
|
+
export function validateToolInput(schema, input) {
|
|
33
|
+
const problems = [];
|
|
34
|
+
try {
|
|
35
|
+
check(schema, input, "", { root: schema, scoped: false, work: { left: MAX_WORK } }, 0, problems);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
// A schema too costly to judge is one the validator cannot judge.
|
|
39
|
+
if (err instanceof WorkExhausted)
|
|
40
|
+
return [];
|
|
41
|
+
throw err;
|
|
42
|
+
}
|
|
43
|
+
return problems;
|
|
44
|
+
}
|
|
45
|
+
/** How many problems the model is told about; the rest are counted. */
|
|
46
|
+
const MAX_REPORTED = 10;
|
|
47
|
+
/**
|
|
48
|
+
* The tool result a call gets when its arguments fail the tool's schema, or
|
|
49
|
+
* `undefined` when they fit. The loop answers the call with this instead of
|
|
50
|
+
* running it, and the model corrects the call within its own budgets.
|
|
51
|
+
*/
|
|
52
|
+
export function invalidInputRefusal(tool, input) {
|
|
53
|
+
let problems;
|
|
54
|
+
try {
|
|
55
|
+
problems = validateToolInput(tool.spec.inputSchema, input);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// A schema the validator trips over is one it cannot judge: the call runs,
|
|
59
|
+
// as it would with validation off, rather than the run failing.
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
if (problems.length === 0)
|
|
63
|
+
return undefined;
|
|
64
|
+
const shown = problems
|
|
65
|
+
.slice(0, MAX_REPORTED)
|
|
66
|
+
.map((p) => `${p.path || "(arguments)"}: ${p.message}`);
|
|
67
|
+
const more = problems.length - shown.length;
|
|
68
|
+
return (`invalid arguments for ${tool.spec.name}; the call was not run. ` +
|
|
69
|
+
`Call it again with arguments that match its input schema: ${shown.join("; ")}` +
|
|
70
|
+
(more > 0 ? `; and ${more} more` : ""));
|
|
71
|
+
}
|
|
72
|
+
/** Deep enough for any real tool schema; a `$ref` cycle stops here instead of looping. */
|
|
73
|
+
const MAX_DEPTH = 32;
|
|
74
|
+
/**
|
|
75
|
+
* How many schema/value checks one validation may make. Shared definitions
|
|
76
|
+
* referenced from several composition branches can multiply the work
|
|
77
|
+
* exponentially without any cycle, and validation runs synchronously before
|
|
78
|
+
* the call, where no deadline can interrupt it; past this the validator gives
|
|
79
|
+
* up and the call runs unjudged.
|
|
80
|
+
*/
|
|
81
|
+
const MAX_WORK = 25_000;
|
|
82
|
+
class WorkExhausted extends Error {
|
|
83
|
+
}
|
|
84
|
+
const isObject = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
|
|
85
|
+
/** The JSON type of a parsed value, as JSON Schema names it. */
|
|
86
|
+
function jsonType(value) {
|
|
87
|
+
if (value === null)
|
|
88
|
+
return "null";
|
|
89
|
+
if (Array.isArray(value))
|
|
90
|
+
return "array";
|
|
91
|
+
if (typeof value === "number")
|
|
92
|
+
return Number.isInteger(value) ? "integer" : "number";
|
|
93
|
+
return typeof value;
|
|
94
|
+
}
|
|
95
|
+
const JSON_TYPES = new Set(["null", "boolean", "object", "array", "number", "integer", "string"]);
|
|
96
|
+
/**
|
|
97
|
+
* The draft the root schema declares in `$schema`: 3 to 7 for draft-03 to
|
|
98
|
+
* draft-07, 2019 for 2019-09, 2020 for 2020-12, or `undefined` when it names
|
|
99
|
+
* none (then every keyword the validator knows applies).
|
|
100
|
+
*/
|
|
101
|
+
function declaredDraft(root) {
|
|
102
|
+
const declared = isObject(root) ? root.$schema : undefined;
|
|
103
|
+
if (typeof declared !== "string")
|
|
104
|
+
return undefined;
|
|
105
|
+
const old = /draft-0([3-7])\b/.exec(declared);
|
|
106
|
+
if (old)
|
|
107
|
+
return Number(old[1]);
|
|
108
|
+
if (declared.includes("2019-09"))
|
|
109
|
+
return 2019;
|
|
110
|
+
if (declared.includes("2020-12"))
|
|
111
|
+
return 2020;
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
/** Whether the root schema declares a draft (03 to 07) in which `$ref` siblings are ignored. */
|
|
115
|
+
function refReplacesSiblings(root) {
|
|
116
|
+
const draft = declaredDraft(root);
|
|
117
|
+
return draft !== undefined && draft <= 7;
|
|
118
|
+
}
|
|
119
|
+
/** Whether a keyword introduced in `since` exists in the draft the root schema declares. */
|
|
120
|
+
function inDraft(root, since) {
|
|
121
|
+
const draft = declaredDraft(root);
|
|
122
|
+
return draft === undefined || draft >= since;
|
|
123
|
+
}
|
|
124
|
+
function typeMatches(expected, actual) {
|
|
125
|
+
return expected === actual || (expected === "number" && actual === "integer");
|
|
126
|
+
}
|
|
127
|
+
function deepEqual(a, b) {
|
|
128
|
+
if (a === b)
|
|
129
|
+
return true;
|
|
130
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
131
|
+
return a.length === b.length && a.every((v, i) => deepEqual(v, b[i]));
|
|
132
|
+
}
|
|
133
|
+
if (isObject(a) && isObject(b)) {
|
|
134
|
+
const keys = Object.keys(a);
|
|
135
|
+
return (keys.length === Object.keys(b).length &&
|
|
136
|
+
keys.every((k) => Object.hasOwn(b, k) && deepEqual(a[k], b[k])));
|
|
137
|
+
}
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
/** A pattern the validator can compile, or `undefined` for one it cannot (then the keyword is ignored). */
|
|
141
|
+
function compile(pattern) {
|
|
142
|
+
if (typeof pattern !== "string")
|
|
143
|
+
return undefined;
|
|
144
|
+
try {
|
|
145
|
+
return new RegExp(pattern, "u");
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
try {
|
|
149
|
+
return new RegExp(pattern);
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/** Resolve a local `#/...` JSON Pointer against the root schema. */
|
|
157
|
+
function resolveRef(root, ref) {
|
|
158
|
+
if (!ref.startsWith("#"))
|
|
159
|
+
return undefined;
|
|
160
|
+
// The fragment is percent-decoded as a whole before it is read as a JSON
|
|
161
|
+
// Pointer (RFC 6901 §6), so an encoded `/` (`%2F`) separates tokens.
|
|
162
|
+
let fragment;
|
|
163
|
+
try {
|
|
164
|
+
fragment = decodeURIComponent(ref.slice(1));
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
// A malformed escape (`%` not followed by two hex digits) names nothing.
|
|
168
|
+
return undefined;
|
|
169
|
+
}
|
|
170
|
+
if (fragment === "")
|
|
171
|
+
return root;
|
|
172
|
+
if (!fragment.startsWith("/"))
|
|
173
|
+
return undefined;
|
|
174
|
+
let node = root;
|
|
175
|
+
for (const raw of fragment.slice(1).split("/")) {
|
|
176
|
+
const key = raw.replaceAll("~1", "/").replaceAll("~0", "~");
|
|
177
|
+
if (!isObject(node) && !Array.isArray(node))
|
|
178
|
+
return undefined;
|
|
179
|
+
node = node[key];
|
|
180
|
+
}
|
|
181
|
+
return node;
|
|
182
|
+
}
|
|
183
|
+
const pointer = (path, key) => `${path}/${String(key).replaceAll("~", "~0").replaceAll("/", "~1")}`;
|
|
184
|
+
const num = (v) => (typeof v === "number" ? v : undefined);
|
|
185
|
+
const quoted = (values) => {
|
|
186
|
+
const shown = values.slice(0, MAX_REPORTED).map((v) => JSON.stringify(v));
|
|
187
|
+
return values.length > shown.length ? `${shown.join(", ")}, …` : shown.join(", ");
|
|
188
|
+
};
|
|
189
|
+
function check(schema, value, path, outer, depth, problems) {
|
|
190
|
+
if (--outer.work.left < 0)
|
|
191
|
+
throw new WorkExhausted();
|
|
192
|
+
if (schema === false) {
|
|
193
|
+
problems.push({ path, message: "is not allowed" });
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (!isObject(schema) || depth > MAX_DEPTH)
|
|
197
|
+
return;
|
|
198
|
+
const s = schema;
|
|
199
|
+
const env = !outer.scoped &&
|
|
200
|
+
schema !== outer.root &&
|
|
201
|
+
(typeof s.$id === "string" || typeof s.id === "string")
|
|
202
|
+
? { ...outer, scoped: true }
|
|
203
|
+
: outer;
|
|
204
|
+
const at = (message) => problems.push({ path, message });
|
|
205
|
+
// OpenAPI's `nullable` admits null whatever else the schema says, composition
|
|
206
|
+
// included (generators emit `{ allOf: [{ $ref }], nullable: true }`).
|
|
207
|
+
if (s.nullable === true && value === null)
|
|
208
|
+
return;
|
|
209
|
+
if (typeof s.$ref === "string") {
|
|
210
|
+
// Inside an embedded resource a local `$ref` means that resource, which
|
|
211
|
+
// this validator does not track, so it is ignored rather than misread.
|
|
212
|
+
const target = env.scoped ? undefined : resolveRef(env.root, s.$ref);
|
|
213
|
+
if (target !== undefined)
|
|
214
|
+
check(target, value, path, env, depth + 1, problems);
|
|
215
|
+
// Before 2019-09 a `$ref` replaced its whole schema object: the keywords
|
|
216
|
+
// beside it are ignored, so they are ignored here too.
|
|
217
|
+
if (refReplacesSiblings(env.root))
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
if (Array.isArray(s.allOf)) {
|
|
221
|
+
for (const branch of s.allOf)
|
|
222
|
+
check(branch, value, path, env, depth + 1, problems);
|
|
223
|
+
}
|
|
224
|
+
for (const key of ["anyOf", "oneOf"]) {
|
|
225
|
+
const branches = s[key];
|
|
226
|
+
if (!Array.isArray(branches) || branches.length === 0)
|
|
227
|
+
continue;
|
|
228
|
+
const fits = branches.some((branch) => {
|
|
229
|
+
const inner = [];
|
|
230
|
+
check(branch, value, path, env, depth + 1, inner);
|
|
231
|
+
return inner.length === 0;
|
|
232
|
+
});
|
|
233
|
+
if (!fits)
|
|
234
|
+
at(`matches none of the ${branches.length} allowed shapes`);
|
|
235
|
+
}
|
|
236
|
+
const actual = jsonType(value);
|
|
237
|
+
const types = typeof s.type === "string" ? [s.type] : Array.isArray(s.type) ? s.type : undefined;
|
|
238
|
+
// A type name outside the seven JSON types (draft 3's `any`, a typo) is a
|
|
239
|
+
// keyword the validator does not know, so the whole `type` check is skipped.
|
|
240
|
+
const knownTypes = types !== undefined &&
|
|
241
|
+
types.length > 0 &&
|
|
242
|
+
types.every((t) => typeof t === "string" && JSON_TYPES.has(t));
|
|
243
|
+
if (types && knownTypes && !types.some((t) => typeMatches(t, actual))) {
|
|
244
|
+
// "integer" is the schema's word for a kind of number, not a type a model writes.
|
|
245
|
+
at(`expected ${types.join(" or ")}, got ${actual === "integer" ? "number" : actual}`);
|
|
246
|
+
// The keywords below would only restate a wrong type as several problems.
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
if (Array.isArray(s.enum) && !s.enum.some((v) => deepEqual(v, value))) {
|
|
250
|
+
at(`must be one of ${quoted(s.enum)}`);
|
|
251
|
+
}
|
|
252
|
+
// `const` arrived in draft 6; an older schema's `const` is an unknown keyword.
|
|
253
|
+
if (Object.hasOwn(s, "const") && inDraft(env.root, 6) && !deepEqual(s.const, value)) {
|
|
254
|
+
at(`must be ${JSON.stringify(s.const)}`);
|
|
255
|
+
}
|
|
256
|
+
if (typeof value === "string") {
|
|
257
|
+
const length = [...value].length;
|
|
258
|
+
const min = num(s.minLength);
|
|
259
|
+
const max = num(s.maxLength);
|
|
260
|
+
if (min !== undefined && length < min)
|
|
261
|
+
at(`must be at least ${min} characters`);
|
|
262
|
+
if (max !== undefined && length > max)
|
|
263
|
+
at(`must be at most ${max} characters`);
|
|
264
|
+
const pattern = compile(s.pattern);
|
|
265
|
+
if (pattern && !pattern.test(value))
|
|
266
|
+
at(`must match the pattern ${String(s.pattern)}`);
|
|
267
|
+
}
|
|
268
|
+
if (typeof value === "number") {
|
|
269
|
+
const min = num(s.minimum);
|
|
270
|
+
const max = num(s.maximum);
|
|
271
|
+
// Draft 4 spelled the exclusive bounds as booleans beside minimum/maximum.
|
|
272
|
+
const exMin = num(s.exclusiveMinimum) ?? (s.exclusiveMinimum === true ? min : undefined);
|
|
273
|
+
const exMax = num(s.exclusiveMaximum) ?? (s.exclusiveMaximum === true ? max : undefined);
|
|
274
|
+
if (min !== undefined && s.exclusiveMinimum !== true && value < min)
|
|
275
|
+
at(`must be >= ${min}`);
|
|
276
|
+
if (max !== undefined && s.exclusiveMaximum !== true && value > max)
|
|
277
|
+
at(`must be <= ${max}`);
|
|
278
|
+
if (exMin !== undefined && value <= exMin)
|
|
279
|
+
at(`must be > ${exMin}`);
|
|
280
|
+
if (exMax !== undefined && value >= exMax)
|
|
281
|
+
at(`must be < ${exMax}`);
|
|
282
|
+
}
|
|
283
|
+
if (Array.isArray(value)) {
|
|
284
|
+
const min = num(s.minItems);
|
|
285
|
+
const max = num(s.maxItems);
|
|
286
|
+
if (min !== undefined && value.length < min)
|
|
287
|
+
at(`must have at least ${min} items`);
|
|
288
|
+
if (max !== undefined && value.length > max)
|
|
289
|
+
at(`must have at most ${max} items`);
|
|
290
|
+
// Positional schemas: `prefixItems` (2020-12) or an `items` array (draft 7).
|
|
291
|
+
// `prefixItems` arrived in 2020-12; under an older declared draft it is unknown.
|
|
292
|
+
const positional = Array.isArray(s.prefixItems) && inDraft(env.root, 2020)
|
|
293
|
+
? s.prefixItems
|
|
294
|
+
: Array.isArray(s.items)
|
|
295
|
+
? s.items
|
|
296
|
+
: [];
|
|
297
|
+
positional.forEach((item, i) => {
|
|
298
|
+
if (i < value.length)
|
|
299
|
+
check(item, value[i], pointer(path, i), env, depth + 1, problems);
|
|
300
|
+
});
|
|
301
|
+
if (!Array.isArray(s.items) && s.items !== undefined) {
|
|
302
|
+
for (let i = positional.length; i < value.length; i += 1) {
|
|
303
|
+
check(s.items, value[i], pointer(path, i), env, depth + 1, problems);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
if (isObject(value)) {
|
|
308
|
+
const properties = isObject(s.properties) ? s.properties : {};
|
|
309
|
+
if (Array.isArray(s.required)) {
|
|
310
|
+
for (const key of s.required) {
|
|
311
|
+
if (typeof key === "string" && !Object.hasOwn(value, key)) {
|
|
312
|
+
problems.push({ path: pointer(path, key), message: "is required" });
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
const min = num(s.minProperties);
|
|
317
|
+
const max = num(s.maxProperties);
|
|
318
|
+
const count = Object.keys(value).length;
|
|
319
|
+
if (min !== undefined && count < min)
|
|
320
|
+
at(`must have at least ${min} properties`);
|
|
321
|
+
if (max !== undefined && count > max)
|
|
322
|
+
at(`must have at most ${max} properties`);
|
|
323
|
+
// A key matched by `patternProperties` is not "additional". If any of its
|
|
324
|
+
// patterns cannot be compiled, nothing can be called additional with
|
|
325
|
+
// confidence, so that check is skipped rather than guessed.
|
|
326
|
+
const patternKeys = isObject(s.patternProperties) ? Object.keys(s.patternProperties) : [];
|
|
327
|
+
const patterns = patternKeys.map(compile);
|
|
328
|
+
const additionalKnown = patterns.every((p) => p !== undefined);
|
|
329
|
+
for (const [key, item] of Object.entries(value)) {
|
|
330
|
+
const where = pointer(path, key);
|
|
331
|
+
if (Object.hasOwn(properties, key)) {
|
|
332
|
+
check(properties[key], item, where, env, depth + 1, problems);
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
if (!additionalKnown || patterns.some((p) => p?.test(key)))
|
|
336
|
+
continue;
|
|
337
|
+
if (s.additionalProperties === false) {
|
|
338
|
+
problems.push({ path: where, message: "is not an allowed property" });
|
|
339
|
+
}
|
|
340
|
+
else if (isObject(s.additionalProperties)) {
|
|
341
|
+
check(s.additionalProperties, item, where, env, depth + 1, problems);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
//# sourceMappingURL=validate.js.map
|