@zackbart/connecta 0.15.1 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +40 -20
- package/CHANGELOG.md +653 -0
- package/README.md +25 -5
- package/bin/connecta.mjs +44 -3
- package/dist/access-tokens.d.ts +0 -1
- package/dist/access-tokens.js +0 -1
- package/dist/activity.d.ts +50 -2
- package/dist/activity.js +34 -1
- package/dist/apps-shell.d.ts +0 -1
- package/dist/apps-shell.js +0 -1
- package/dist/auth/bearer.d.ts +0 -1
- package/dist/auth/bearer.js +0 -1
- package/dist/auth/clerk.d.ts +0 -1
- package/dist/auth/clerk.js +45 -9
- package/dist/auth/downstream-oauth.d.ts +0 -1
- package/dist/auth/downstream-oauth.js +0 -1
- package/dist/call-admission.d.ts +0 -1
- package/dist/call-admission.js +0 -1
- package/dist/catalog-drift.d.ts +99 -0
- package/dist/catalog-drift.js +251 -0
- package/dist/catalog-fingerprint.d.ts +0 -1
- package/dist/catalog-fingerprint.js +0 -1
- package/dist/catalog-limits.d.ts +0 -1
- package/dist/catalog-limits.js +0 -1
- package/dist/catalog-service.d.ts +0 -1
- package/dist/catalog-service.js +41 -5
- package/dist/catalog.d.ts +11 -1
- package/dist/catalog.js +20 -1
- package/dist/concurrency.d.ts +0 -1
- package/dist/concurrency.js +0 -1
- package/dist/connector-scope.d.ts +0 -1
- package/dist/connector-scope.js +0 -1
- package/dist/connectors/api.d.ts +29 -21
- package/dist/connectors/api.js +45 -19
- package/dist/connectors/guarded-fetch.d.ts +106 -0
- package/dist/connectors/guarded-fetch.js +289 -0
- package/dist/connectors/remote-mcp.d.ts +0 -1
- package/dist/connectors/remote-mcp.js +0 -1
- package/dist/credentials.d.ts +0 -1
- package/dist/credentials.js +0 -1
- package/dist/errors.d.ts +30 -3
- package/dist/errors.js +1 -1
- package/dist/execute.d.ts +0 -1
- package/dist/execute.js +0 -1
- package/dist/executor-admission.d.ts +11 -1
- package/dist/executor-admission.js +28 -1
- package/dist/executor-result.d.ts +0 -1
- package/dist/executor-result.js +0 -1
- package/dist/executors/quickjs-child.d.ts +0 -1
- package/dist/executors/quickjs-child.js +0 -1
- package/dist/executors/quickjs-protocol.d.ts +0 -1
- package/dist/executors/quickjs-protocol.js +0 -1
- package/dist/executors/quickjs-runtime.d.ts +0 -1
- package/dist/executors/quickjs-runtime.js +0 -1
- package/dist/executors/quickjs.d.ts +0 -1
- package/dist/executors/quickjs.js +2 -1
- package/dist/favicon.d.ts +0 -1
- package/dist/favicon.js +0 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.js +24 -7
- package/dist/invocation.d.ts +0 -1
- package/dist/invocation.js +0 -1
- package/dist/json-schema.d.ts +0 -1
- package/dist/json-schema.js +0 -1
- package/dist/mcp-result.d.ts +0 -1
- package/dist/mcp-result.js +0 -1
- package/dist/meta-tools.d.ts +0 -1
- package/dist/meta-tools.js +0 -1
- package/dist/node.d.ts +0 -1
- package/dist/node.js +0 -1
- package/dist/operator-ui/generated.d.ts +2 -3
- package/dist/operator-ui/generated.js +3 -4
- package/dist/operator-ui/model.d.ts +10 -1
- package/dist/operator-ui/model.js +0 -1
- package/dist/operator-ui/view.d.ts +167 -0
- package/dist/operator-ui/view.js +270 -0
- package/dist/providers/cloudflare.d.ts +0 -1
- package/dist/providers/cloudflare.js +261 -299
- package/dist/providers/linear.d.ts +26 -5
- package/dist/providers/linear.js +32 -61
- package/dist/providers/mixpanel.d.ts +35 -4
- package/dist/providers/mixpanel.js +53 -79
- package/dist/providers/notion.d.ts +0 -1
- package/dist/providers/notion.js +87 -42
- package/dist/providers/stripe.d.ts +13 -1
- package/dist/providers/stripe.js +31 -60
- package/dist/registry.d.ts +34 -2
- package/dist/registry.js +85 -5
- package/dist/retired-toolkits.d.ts +0 -1
- package/dist/retired-toolkits.js +0 -1
- package/dist/routes/access-tokens.d.ts +0 -1
- package/dist/routes/access-tokens.js +0 -1
- package/dist/routes/activity.d.ts +0 -1
- package/dist/routes/activity.js +0 -1
- package/dist/routes/credentials.d.ts +0 -1
- package/dist/routes/credentials.js +0 -1
- package/dist/routes/mcp.d.ts +0 -1
- package/dist/routes/mcp.js +0 -1
- package/dist/routes/oauth.d.ts +0 -1
- package/dist/routes/oauth.js +0 -1
- package/dist/routes/shared.d.ts +2 -1
- package/dist/routes/shared.js +0 -1
- package/dist/routes/ui.d.ts +0 -1
- package/dist/routes/ui.js +0 -1
- package/dist/server.d.ts +0 -1
- package/dist/server.js +11 -1
- package/dist/skills.d.ts +0 -1
- package/dist/skills.js +0 -1
- package/dist/storage/file.d.ts +0 -1
- package/dist/storage/file.js +0 -1
- package/dist/storage/memory.d.ts +0 -1
- package/dist/storage/memory.js +0 -1
- package/dist/timeout.d.ts +0 -1
- package/dist/timeout.js +0 -1
- package/dist/tool-safety.d.ts +0 -1
- package/dist/tool-safety.js +0 -1
- package/dist/types.d.ts +45 -1
- package/dist/types.js +0 -1
- package/dist/ui.d.ts +0 -1
- package/dist/ui.js +13 -137
- package/dist/validate.d.ts +13 -15
- package/dist/validate.js +24 -11
- package/dist/version.d.ts +1 -2
- package/dist/version.js +1 -2
- package/documentation/architecture.md +186 -5
- package/documentation/auth.md +11 -0
- package/documentation/call-admission.md +142 -6
- package/documentation/cloudflare.md +92 -10
- package/documentation/code-first-exploration.md +2 -2
- package/documentation/code-mode.md +14 -14
- package/documentation/connector-guides.md +172 -5
- package/documentation/connectors.md +89 -0
- package/documentation/linear.md +20 -2
- package/documentation/mcp-ui-design.md +2 -2
- package/documentation/meta-tools.md +7 -1
- package/documentation/mixpanel.md +42 -9
- package/documentation/notion.md +23 -2
- package/documentation/operations.md +325 -5
- package/documentation/operator-ui.md +120 -5
- package/documentation/provider-audit.md +160 -0
- package/documentation/provider-conventions.md +667 -0
- package/documentation/request-admission.md +167 -5
- package/documentation/rich-output-design.md +1 -2
- package/documentation/stripe.md +15 -0
- package/documentation/upgrading.md +454 -0
- package/ethos.md +14 -9
- package/examples/worker/README.md +102 -12
- package/examples/worker/src/index.ts +46 -1
- package/examples/worker/wrangler.jsonc +14 -1
- package/package.json +10 -6
- package/templates/node/.dockerignore +10 -0
- package/templates/node/.env.example +40 -3
- package/templates/node/AGENTS.md +16 -1
- package/templates/node/Dockerfile +49 -0
- package/templates/node/README.md +117 -2
- package/templates/node/docker-compose.yml +39 -0
- package/templates/node/package.json +1 -1
- package/templates/node/src/file-activity.ts +182 -0
- package/templates/node/src/index.ts +80 -4
- package/assets/connecta-clay-hero.png +0 -0
- package/dist/access-tokens.d.ts.map +0 -1
- package/dist/access-tokens.js.map +0 -1
- package/dist/activity.d.ts.map +0 -1
- package/dist/activity.js.map +0 -1
- package/dist/apps-shell.d.ts.map +0 -1
- package/dist/apps-shell.js.map +0 -1
- package/dist/auth/bearer.d.ts.map +0 -1
- package/dist/auth/bearer.js.map +0 -1
- package/dist/auth/clerk.d.ts.map +0 -1
- package/dist/auth/clerk.js.map +0 -1
- package/dist/auth/downstream-oauth.d.ts.map +0 -1
- package/dist/auth/downstream-oauth.js.map +0 -1
- package/dist/call-admission.d.ts.map +0 -1
- package/dist/call-admission.js.map +0 -1
- package/dist/catalog-fingerprint.d.ts.map +0 -1
- package/dist/catalog-fingerprint.js.map +0 -1
- package/dist/catalog-limits.d.ts.map +0 -1
- package/dist/catalog-limits.js.map +0 -1
- package/dist/catalog-service.d.ts.map +0 -1
- package/dist/catalog-service.js.map +0 -1
- package/dist/catalog.d.ts.map +0 -1
- package/dist/catalog.js.map +0 -1
- package/dist/concurrency.d.ts.map +0 -1
- package/dist/concurrency.js.map +0 -1
- package/dist/connector-scope.d.ts.map +0 -1
- package/dist/connector-scope.js.map +0 -1
- package/dist/connectors/api.d.ts.map +0 -1
- package/dist/connectors/api.js.map +0 -1
- package/dist/connectors/remote-mcp.d.ts.map +0 -1
- package/dist/connectors/remote-mcp.js.map +0 -1
- package/dist/credentials.d.ts.map +0 -1
- package/dist/credentials.js.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js.map +0 -1
- package/dist/execute.d.ts.map +0 -1
- package/dist/execute.js.map +0 -1
- package/dist/executor-admission.d.ts.map +0 -1
- package/dist/executor-admission.js.map +0 -1
- package/dist/executor-result.d.ts.map +0 -1
- package/dist/executor-result.js.map +0 -1
- package/dist/executors/quickjs-child.d.ts.map +0 -1
- package/dist/executors/quickjs-child.js.map +0 -1
- package/dist/executors/quickjs-protocol.d.ts.map +0 -1
- package/dist/executors/quickjs-protocol.js.map +0 -1
- package/dist/executors/quickjs-runtime.d.ts.map +0 -1
- package/dist/executors/quickjs-runtime.js.map +0 -1
- package/dist/executors/quickjs.d.ts.map +0 -1
- package/dist/executors/quickjs.js.map +0 -1
- package/dist/favicon.d.ts.map +0 -1
- package/dist/favicon.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/invocation.d.ts.map +0 -1
- package/dist/invocation.js.map +0 -1
- package/dist/json-schema.d.ts.map +0 -1
- package/dist/json-schema.js.map +0 -1
- package/dist/mcp-result.d.ts.map +0 -1
- package/dist/mcp-result.js.map +0 -1
- package/dist/meta-tools.d.ts.map +0 -1
- package/dist/meta-tools.js.map +0 -1
- package/dist/node.d.ts.map +0 -1
- package/dist/node.js.map +0 -1
- package/dist/operator-ui/generated.d.ts.map +0 -1
- package/dist/operator-ui/generated.js.map +0 -1
- package/dist/operator-ui/model.d.ts.map +0 -1
- package/dist/operator-ui/model.js.map +0 -1
- package/dist/providers/cloudflare.d.ts.map +0 -1
- package/dist/providers/cloudflare.js.map +0 -1
- package/dist/providers/linear.d.ts.map +0 -1
- package/dist/providers/linear.js.map +0 -1
- package/dist/providers/mixpanel.d.ts.map +0 -1
- package/dist/providers/mixpanel.js.map +0 -1
- package/dist/providers/notion.d.ts.map +0 -1
- package/dist/providers/notion.js.map +0 -1
- package/dist/providers/stripe.d.ts.map +0 -1
- package/dist/providers/stripe.js.map +0 -1
- package/dist/registry.d.ts.map +0 -1
- package/dist/registry.js.map +0 -1
- package/dist/retired-toolkits.d.ts.map +0 -1
- package/dist/retired-toolkits.js.map +0 -1
- package/dist/routes/access-tokens.d.ts.map +0 -1
- package/dist/routes/access-tokens.js.map +0 -1
- package/dist/routes/activity.d.ts.map +0 -1
- package/dist/routes/activity.js.map +0 -1
- package/dist/routes/credentials.d.ts.map +0 -1
- package/dist/routes/credentials.js.map +0 -1
- package/dist/routes/mcp.d.ts.map +0 -1
- package/dist/routes/mcp.js.map +0 -1
- package/dist/routes/oauth.d.ts.map +0 -1
- package/dist/routes/oauth.js.map +0 -1
- package/dist/routes/shared.d.ts.map +0 -1
- package/dist/routes/shared.js.map +0 -1
- package/dist/routes/ui.d.ts.map +0 -1
- package/dist/routes/ui.js.map +0 -1
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/skills.d.ts.map +0 -1
- package/dist/skills.js.map +0 -1
- package/dist/storage/file.d.ts.map +0 -1
- package/dist/storage/file.js.map +0 -1
- package/dist/storage/memory.d.ts.map +0 -1
- package/dist/storage/memory.js.map +0 -1
- package/dist/timeout.d.ts.map +0 -1
- package/dist/timeout.js.map +0 -1
- package/dist/tool-safety.d.ts.map +0 -1
- package/dist/tool-safety.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/ui.d.ts.map +0 -1
- package/dist/ui.js.map +0 -1
- package/dist/validate.d.ts.map +0 -1
- package/dist/validate.js.map +0 -1
- package/dist/version.d.ts.map +0 -1
- package/dist/version.js.map +0 -1
- package/examples/node/README.md +0 -52
- package/examples/node/src/index.ts +0 -71
- package/src/access-tokens.ts +0 -289
- package/src/activity.ts +0 -234
- package/src/apps-shell.ts +0 -370
- package/src/auth/bearer.ts +0 -61
- package/src/auth/clerk.ts +0 -553
- package/src/auth/downstream-oauth.ts +0 -575
- package/src/call-admission.ts +0 -521
- package/src/catalog-fingerprint.ts +0 -52
- package/src/catalog-limits.ts +0 -11
- package/src/catalog-service.ts +0 -1153
- package/src/catalog.ts +0 -790
- package/src/concurrency.ts +0 -39
- package/src/connector-scope.ts +0 -66
- package/src/connectors/api.ts +0 -159
- package/src/connectors/remote-mcp.ts +0 -1090
- package/src/credentials.ts +0 -428
- package/src/errors.ts +0 -364
- package/src/execute.ts +0 -1406
- package/src/executor-admission.ts +0 -328
- package/src/executor-result.ts +0 -107
- package/src/executors/quickjs-child.ts +0 -172
- package/src/executors/quickjs-protocol.ts +0 -99
- package/src/executors/quickjs-runtime.ts +0 -470
- package/src/executors/quickjs.ts +0 -776
- package/src/favicon.ts +0 -53
- package/src/index.ts +0 -666
- package/src/invocation.ts +0 -655
- package/src/json-schema.ts +0 -11
- package/src/mcp-result.ts +0 -43
- package/src/meta-tools.ts +0 -1607
- package/src/node.ts +0 -206
- package/src/operator-ui/browser.css +0 -423
- package/src/operator-ui/browser.ts +0 -1281
- package/src/operator-ui/generated.ts +0 -4
- package/src/operator-ui/model.ts +0 -111
- package/src/providers/cloudflare.ts +0 -3999
- package/src/providers/linear.ts +0 -302
- package/src/providers/mixpanel.ts +0 -229
- package/src/providers/notion.ts +0 -1879
- package/src/providers/stripe.ts +0 -307
- package/src/registry.ts +0 -1085
- package/src/retired-toolkits.ts +0 -14
- package/src/routes/access-tokens.ts +0 -115
- package/src/routes/activity.ts +0 -215
- package/src/routes/credentials.ts +0 -254
- package/src/routes/mcp.ts +0 -429
- package/src/routes/oauth.ts +0 -322
- package/src/routes/shared.ts +0 -247
- package/src/routes/ui.ts +0 -152
- package/src/server.ts +0 -195
- package/src/skills.ts +0 -271
- package/src/storage/file.ts +0 -123
- package/src/storage/memory.ts +0 -44
- package/src/timeout.ts +0 -84
- package/src/tool-safety.ts +0 -15
- package/src/types.ts +0 -523
- package/src/ui.ts +0 -744
- package/src/validate.ts +0 -387
- package/src/version.ts +0 -7
package/src/validate.ts
DELETED
|
@@ -1,387 +0,0 @@
|
|
|
1
|
-
import { Validator } from "@cfworker/json-schema";
|
|
2
|
-
import { ConnectorCallError } from "./errors.js";
|
|
3
|
-
import type {
|
|
4
|
-
ArgumentValidationDetails,
|
|
5
|
-
ArgumentValidationIssue,
|
|
6
|
-
} from "./errors.js";
|
|
7
|
-
import { MAX_ARGUMENT_VALIDATION_ISSUES } from "./errors.js";
|
|
8
|
-
import type { JsonSchema, Logger } from "./types.js";
|
|
9
|
-
|
|
10
|
-
export interface ValidateToolInputOptions {
|
|
11
|
-
/**
|
|
12
|
-
* Tool address used in the error and warning text, conventionally
|
|
13
|
-
* `"connectorId.toolName"`.
|
|
14
|
-
*/
|
|
15
|
-
address: string;
|
|
16
|
-
/**
|
|
17
|
-
* Destination for the one-time warning emitted when a schema turns out to be
|
|
18
|
-
* unusable. Default console.
|
|
19
|
-
*/
|
|
20
|
-
logger?: Logger;
|
|
21
|
-
/**
|
|
22
|
-
* Fail-closed on a schema the validator cannot evaluate (default false =
|
|
23
|
-
* today's fail-open behavior). When true, a schema that cannot be compiled —
|
|
24
|
-
* or that only fails on first use, e.g. an unresolvable `$ref` — yields a
|
|
25
|
-
* non-retryable `invalid_args` error instead of passing the raw arguments
|
|
26
|
-
* through, so unvalidated input is never silently admitted. The happy path
|
|
27
|
-
* (a schema that compiles and validates) is unaffected.
|
|
28
|
-
*/
|
|
29
|
-
failClosed?: boolean;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export interface PrecompileValidatorOptions {
|
|
33
|
-
/**
|
|
34
|
-
* Tool address used in the warning text, conventionally
|
|
35
|
-
* `"connectorId.toolName"`.
|
|
36
|
-
*/
|
|
37
|
-
address: string;
|
|
38
|
-
/**
|
|
39
|
-
* Destination for the warning emitted when the schema cannot be compiled.
|
|
40
|
-
* Default console.
|
|
41
|
-
*/
|
|
42
|
-
logger?: Logger;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Lazy validator cache keyed by the schema object itself; null marks a schema
|
|
46
|
-
// the validator rejected (warned once, then passed through rather than
|
|
47
|
-
// breaking a working tool). A WeakMap so schemas belonging to a discarded
|
|
48
|
-
// connector are collectable, the same pattern compactSchema uses.
|
|
49
|
-
const validators = new WeakMap<JsonSchema, Validator | null>();
|
|
50
|
-
const REQUIRED_PROPERTY_RE =
|
|
51
|
-
/^Instance does not have required property "([^"]+)"\.$/;
|
|
52
|
-
|
|
53
|
-
interface ValidationUnit {
|
|
54
|
-
keyword: string;
|
|
55
|
-
keywordLocation: string;
|
|
56
|
-
instanceLocation: string;
|
|
57
|
-
error: string;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const CONTAINER_VALIDATION_KEYWORDS = new Set([
|
|
61
|
-
"properties",
|
|
62
|
-
"items",
|
|
63
|
-
"allOf",
|
|
64
|
-
"anyOf",
|
|
65
|
-
"oneOf",
|
|
66
|
-
"if",
|
|
67
|
-
"not",
|
|
68
|
-
"patternProperties",
|
|
69
|
-
"additionalProperties",
|
|
70
|
-
]);
|
|
71
|
-
|
|
72
|
-
function decodePointerPart(value: string): string {
|
|
73
|
-
return value.replaceAll("~1", "/").replaceAll("~0", "~");
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function encodePointerPart(value: string): string {
|
|
77
|
-
return value.replaceAll("~", "~0").replaceAll("/", "~1");
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function pointerValue(value: unknown, pointer: string): unknown {
|
|
81
|
-
if (pointer === "#") return value;
|
|
82
|
-
if (!pointer.startsWith("#/")) return undefined;
|
|
83
|
-
let current = value;
|
|
84
|
-
for (const part of pointer.slice(2).split("/").map(decodePointerPart)) {
|
|
85
|
-
if (current === null || typeof current !== "object") return undefined;
|
|
86
|
-
current = (current as Record<string, unknown>)[part];
|
|
87
|
-
}
|
|
88
|
-
return current;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function argumentPath(location: string): string {
|
|
92
|
-
if (location === "#") return "/";
|
|
93
|
-
return location.startsWith("#") ? location.slice(1) || "/" : "/";
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function validationUnitKey(unit: ValidationUnit): string {
|
|
97
|
-
return JSON.stringify([
|
|
98
|
-
unit.keyword,
|
|
99
|
-
unit.keywordLocation,
|
|
100
|
-
unit.instanceLocation,
|
|
101
|
-
unit.error,
|
|
102
|
-
]);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function childPropertyName(
|
|
106
|
-
parentLocation: string,
|
|
107
|
-
childLocation: string,
|
|
108
|
-
): string | undefined {
|
|
109
|
-
const prefix = parentLocation === "#" ? "#/" : `${parentLocation}/`;
|
|
110
|
-
if (!childLocation.startsWith(prefix)) return undefined;
|
|
111
|
-
const encoded = childLocation.slice(prefix.length);
|
|
112
|
-
return !encoded.includes("/") ? decodePointerPart(encoded) : undefined;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function schemaDeclaresProperty(schema: unknown, property: string): boolean {
|
|
116
|
-
if (schema === null || typeof schema !== "object" || Array.isArray(schema)) {
|
|
117
|
-
return false;
|
|
118
|
-
}
|
|
119
|
-
const record = schema as Record<string, unknown>;
|
|
120
|
-
const properties = record.properties;
|
|
121
|
-
if (
|
|
122
|
-
properties !== null &&
|
|
123
|
-
typeof properties === "object" &&
|
|
124
|
-
!Array.isArray(properties) &&
|
|
125
|
-
Object.hasOwn(properties, property)
|
|
126
|
-
) {
|
|
127
|
-
return true;
|
|
128
|
-
}
|
|
129
|
-
const patterns = record.patternProperties;
|
|
130
|
-
if (
|
|
131
|
-
patterns === null ||
|
|
132
|
-
typeof patterns !== "object" ||
|
|
133
|
-
Array.isArray(patterns)
|
|
134
|
-
) {
|
|
135
|
-
return false;
|
|
136
|
-
}
|
|
137
|
-
for (const pattern of Object.keys(patterns)) {
|
|
138
|
-
try {
|
|
139
|
-
if (new RegExp(pattern).test(property)) return true;
|
|
140
|
-
} catch {
|
|
141
|
-
// The validator owns schema support. An unusable pattern cannot prove
|
|
142
|
-
// that this additional-properties branch is a duplicate.
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
return false;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
function isDuplicateAdditionalPropertiesBranch(
|
|
149
|
-
schema: JsonSchema,
|
|
150
|
-
units: ValidationUnit[],
|
|
151
|
-
index: number,
|
|
152
|
-
): boolean {
|
|
153
|
-
const unit = units[index];
|
|
154
|
-
const wrapper = units[index - 1];
|
|
155
|
-
if (
|
|
156
|
-
unit?.keyword !== "false" ||
|
|
157
|
-
wrapper?.keyword !== "additionalProperties" ||
|
|
158
|
-
!wrapper.keywordLocation.endsWith("/additionalProperties")
|
|
159
|
-
) {
|
|
160
|
-
return false;
|
|
161
|
-
}
|
|
162
|
-
const property = childPropertyName(
|
|
163
|
-
wrapper.instanceLocation,
|
|
164
|
-
unit.instanceLocation,
|
|
165
|
-
);
|
|
166
|
-
if (property === undefined) return false;
|
|
167
|
-
const parentSchemaLocation = wrapper.keywordLocation.slice(
|
|
168
|
-
0,
|
|
169
|
-
-"/additionalProperties".length,
|
|
170
|
-
);
|
|
171
|
-
return schemaDeclaresProperty(
|
|
172
|
-
pointerValue(schema, parentSchemaLocation || "#"),
|
|
173
|
-
property,
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
function normalizedValidationUnits(
|
|
178
|
-
schema: JsonSchema,
|
|
179
|
-
units: ValidationUnit[],
|
|
180
|
-
): ValidationUnit[] {
|
|
181
|
-
const seen = new Set<string>();
|
|
182
|
-
return units.filter((unit, index) => {
|
|
183
|
-
if (CONTAINER_VALIDATION_KEYWORDS.has(unit.keyword)) return false;
|
|
184
|
-
if (isDuplicateAdditionalPropertiesBranch(schema, units, index)) {
|
|
185
|
-
return false;
|
|
186
|
-
}
|
|
187
|
-
const key = validationUnitKey(unit);
|
|
188
|
-
if (seen.has(key)) return false;
|
|
189
|
-
seen.add(key);
|
|
190
|
-
return true;
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
function agentFacingValidationError(unit: ValidationUnit): string {
|
|
195
|
-
return unit.keyword === "false"
|
|
196
|
-
? "Value is not allowed by the declared schema."
|
|
197
|
-
: unit.error;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
function expectedType(schema: JsonSchema, unit: ValidationUnit): string | undefined {
|
|
201
|
-
if (unit.keyword === "type") {
|
|
202
|
-
const value = pointerValue(schema, unit.keywordLocation);
|
|
203
|
-
if (typeof value === "string") return value;
|
|
204
|
-
if (Array.isArray(value) && value.every((item) => typeof item === "string")) {
|
|
205
|
-
return value.join(" | ");
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
if (unit.keyword === "required") {
|
|
209
|
-
const missing = REQUIRED_PROPERTY_RE.exec(unit.error)?.[1];
|
|
210
|
-
if (!missing) return undefined;
|
|
211
|
-
const parentLocation = unit.keywordLocation.replace(/\/required$/, "");
|
|
212
|
-
const value = pointerValue(
|
|
213
|
-
schema,
|
|
214
|
-
`${parentLocation}/properties/${encodePointerPart(missing)}/type`,
|
|
215
|
-
);
|
|
216
|
-
if (typeof value === "string") return value;
|
|
217
|
-
if (Array.isArray(value) && value.every((item) => typeof item === "string")) {
|
|
218
|
-
return value.join(" | ");
|
|
219
|
-
}
|
|
220
|
-
return "present";
|
|
221
|
-
}
|
|
222
|
-
const fixed: Record<string, string> = {
|
|
223
|
-
additionalProperties: "no additional properties",
|
|
224
|
-
enum: "one of the declared values",
|
|
225
|
-
const: "the declared constant",
|
|
226
|
-
minLength: "the declared minimum length",
|
|
227
|
-
maxLength: "the declared maximum length",
|
|
228
|
-
minimum: "the declared minimum",
|
|
229
|
-
maximum: "the declared maximum",
|
|
230
|
-
pattern: "the declared string pattern",
|
|
231
|
-
};
|
|
232
|
-
return fixed[unit.keyword];
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
function validationDetails(
|
|
236
|
-
schema: JsonSchema,
|
|
237
|
-
units: ValidationUnit[],
|
|
238
|
-
): ArgumentValidationDetails {
|
|
239
|
-
const issues: ArgumentValidationIssue[] = [];
|
|
240
|
-
for (const unit of units) {
|
|
241
|
-
const missing =
|
|
242
|
-
unit.keyword === "required"
|
|
243
|
-
? REQUIRED_PROPERTY_RE.exec(unit.error)?.[1]
|
|
244
|
-
: undefined;
|
|
245
|
-
const path =
|
|
246
|
-
missing !== undefined
|
|
247
|
-
? `${argumentPath(unit.instanceLocation).replace(/\/$/, "")}/${encodePointerPart(missing)}`
|
|
248
|
-
: argumentPath(unit.instanceLocation);
|
|
249
|
-
const code = unit.keyword === "false" ? "additionalProperties" : unit.keyword;
|
|
250
|
-
const expected =
|
|
251
|
-
expectedType(schema, unit) ??
|
|
252
|
-
(code === "additionalProperties"
|
|
253
|
-
? "no additional properties"
|
|
254
|
-
: "the declared schema constraint");
|
|
255
|
-
const issue = { path, code, expected };
|
|
256
|
-
if (
|
|
257
|
-
!issues.some(
|
|
258
|
-
(existing) =>
|
|
259
|
-
existing.path === issue.path &&
|
|
260
|
-
existing.code === issue.code &&
|
|
261
|
-
existing.expected === issue.expected,
|
|
262
|
-
)
|
|
263
|
-
) {
|
|
264
|
-
issues.push(issue);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
return {
|
|
268
|
-
issues: issues.slice(0, MAX_ARGUMENT_VALIDATION_ISSUES),
|
|
269
|
-
...(issues.length > MAX_ARGUMENT_VALIDATION_ISSUES
|
|
270
|
-
? { truncated: true as const }
|
|
271
|
-
: {}),
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
function unevaluableSchema(address: string): ConnectorCallError {
|
|
276
|
-
return new ConnectorCallError(
|
|
277
|
-
"invalid_args",
|
|
278
|
-
`Cannot validate arguments for "${address}": its inputSchema could not be evaluated`,
|
|
279
|
-
);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
function disableValidation(
|
|
283
|
-
schema: JsonSchema,
|
|
284
|
-
address: string,
|
|
285
|
-
logger: Logger,
|
|
286
|
-
err: unknown,
|
|
287
|
-
): void {
|
|
288
|
-
validators.set(schema, null);
|
|
289
|
-
logger.warn(
|
|
290
|
-
`[connecta] tool "${address}" has an inputSchema the validator cannot use (${
|
|
291
|
-
err instanceof Error ? err.message : String(err)
|
|
292
|
-
}) — arguments are not validated`,
|
|
293
|
-
);
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
/**
|
|
297
|
-
* Validate call arguments against a tool's JSON Schema.
|
|
298
|
-
*
|
|
299
|
-
* Returns a non-retryable `invalid_args` ConnectorCallError describing the
|
|
300
|
-
* mismatch, or null when the arguments are acceptable. It deliberately returns
|
|
301
|
-
* rather than throws: the caller decides what to do with the failure, which is
|
|
302
|
-
* what lets a connector own its error prose, or strip connector-wide
|
|
303
|
-
* convention arguments (a `confirm` flag on writes, say) that individual tool
|
|
304
|
-
* schemas do not declare before deciding the call is really invalid.
|
|
305
|
-
*
|
|
306
|
-
* A schema the validator cannot compile (or that only fails on first use, e.g.
|
|
307
|
-
* an unresolvable `$ref`) is warned about once and then passed through — a
|
|
308
|
-
* broken schema should not break an otherwise working tool. Pass
|
|
309
|
-
* `failClosed: true` to instead reject such calls with `invalid_args`, for
|
|
310
|
-
* callers that would rather refuse a call than forward unvalidated arguments.
|
|
311
|
-
*
|
|
312
|
-
* The compiled validator is cached by **schema object identity**, so pass a
|
|
313
|
-
* stable object: hold the parsed manifest and hand the same schema back on
|
|
314
|
-
* every call. A schema rebuilt per call is a cache miss every time — it still
|
|
315
|
-
* validates correctly, but recompiles the validator on each call, silently and
|
|
316
|
-
* with nothing to show for it but latency.
|
|
317
|
-
*
|
|
318
|
-
* `api()` uses this internally; it is exported for connectors that implement
|
|
319
|
-
* the `Connector` interface directly.
|
|
320
|
-
*/
|
|
321
|
-
export function validateToolInput(
|
|
322
|
-
schema: JsonSchema,
|
|
323
|
-
args: unknown,
|
|
324
|
-
opts: ValidateToolInputOptions,
|
|
325
|
-
): ConnectorCallError | null {
|
|
326
|
-
const logger = opts.logger ?? console;
|
|
327
|
-
let validator = validators.get(schema);
|
|
328
|
-
if (validator === undefined) {
|
|
329
|
-
try {
|
|
330
|
-
validator = new Validator(schema as never, "2020-12", false);
|
|
331
|
-
validators.set(schema, validator);
|
|
332
|
-
} catch (err) {
|
|
333
|
-
disableValidation(schema, opts.address, logger, err);
|
|
334
|
-
validator = null;
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
// A schema the validator could not compile (or that a prior call disabled):
|
|
338
|
-
// pass through by default, refuse when the caller opted into fail-closed.
|
|
339
|
-
if (validator === null) {
|
|
340
|
-
return opts.failClosed ? unevaluableSchema(opts.address) : null;
|
|
341
|
-
}
|
|
342
|
-
let result;
|
|
343
|
-
try {
|
|
344
|
-
result = validator.validate(args);
|
|
345
|
-
} catch (err) {
|
|
346
|
-
// e.g. an unresolvable $ref — surfaces on first validate, not compile.
|
|
347
|
-
disableValidation(schema, opts.address, logger, err);
|
|
348
|
-
return opts.failClosed ? unevaluableSchema(opts.address) : null;
|
|
349
|
-
}
|
|
350
|
-
if (result && !result.valid) {
|
|
351
|
-
const units = normalizedValidationUnits(schema, result.errors);
|
|
352
|
-
const nestedUnits = units.filter((unit) => unit.instanceLocation !== "#");
|
|
353
|
-
const detail = (nestedUnits.length > 0 ? nestedUnits : units)
|
|
354
|
-
.slice(0, MAX_ARGUMENT_VALIDATION_ISSUES)
|
|
355
|
-
.map((unit) =>
|
|
356
|
-
`${unit.instanceLocation}: ${agentFacingValidationError(unit)}`,
|
|
357
|
-
)
|
|
358
|
-
.join("; ");
|
|
359
|
-
return new ConnectorCallError(
|
|
360
|
-
"invalid_args",
|
|
361
|
-
`Invalid arguments for "${opts.address}": ${detail || "input does not match the tool's inputSchema"}`,
|
|
362
|
-
{ validation: validationDetails(schema, units) },
|
|
363
|
-
);
|
|
364
|
-
}
|
|
365
|
-
return null;
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
/**
|
|
369
|
-
* Eagerly compile and cache a tool's inputSchema so a schema the validator
|
|
370
|
-
* cannot use surfaces once at connector construction rather than silently on
|
|
371
|
-
* the first call. Reuses the same module-level cache `validateToolInput` reads,
|
|
372
|
-
* so the runtime path hits the cache. Warning-only: it never throws and never
|
|
373
|
-
* changes call behavior. A schema that only fails on first `validate()` (e.g.
|
|
374
|
-
* an unresolvable `$ref`) still slips through here and is caught at call time.
|
|
375
|
-
*/
|
|
376
|
-
export function precompileValidator(
|
|
377
|
-
schema: JsonSchema,
|
|
378
|
-
opts: PrecompileValidatorOptions,
|
|
379
|
-
): void {
|
|
380
|
-
if (validators.has(schema)) return;
|
|
381
|
-
const logger = opts.logger ?? console;
|
|
382
|
-
try {
|
|
383
|
-
validators.set(schema, new Validator(schema as never, "2020-12", false));
|
|
384
|
-
} catch (err) {
|
|
385
|
-
disableValidation(schema, opts.address, logger, err);
|
|
386
|
-
}
|
|
387
|
-
}
|
package/src/version.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The package version, as a Workers-safe constant — no filesystem read, no
|
|
3
|
-
* import assertion. `test/version.test.ts` asserts it matches package.json, so
|
|
4
|
-
* a bump that forgets this file fails the build rather than shipping a stale
|
|
5
|
-
* version to `/health` and to downstream MCP handshakes.
|
|
6
|
-
*/
|
|
7
|
-
export const CONNECTA_VERSION = "0.15.1";
|