toolcraft 0.0.232 → 0.0.233
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/composition.json +3 -3
- package/dist/applied-default.d.ts +3 -0
- package/dist/applied-default.js +16 -0
- package/dist/cli.js +508 -204
- package/dist/composition.json +3 -3
- package/dist/discriminator.d.ts +9 -0
- package/dist/discriminator.js +32 -0
- package/dist/error-report.d.ts +2 -18
- package/dist/error-report.js +12 -14
- package/dist/http.js +8 -1
- package/dist/human-in-loop/gate.js +6 -0
- package/dist/index.compile-check.js +22 -5
- package/dist/index.d.ts +12 -5
- package/dist/index.js +50 -0
- package/dist/json-schema-converter.d.ts +14 -6
- package/dist/json-schema-converter.js +150 -20
- package/dist/mcp-proxy-metadata.d.ts +2 -0
- package/dist/mcp-proxy-metadata.js +13 -0
- package/dist/mcp-proxy.d.ts +1 -0
- package/dist/mcp-proxy.js +65 -47
- package/dist/mcp-result.d.ts +3 -0
- package/dist/mcp-result.js +10 -0
- package/dist/mcp.js +211 -153
- package/dist/redaction.js +26 -17
- package/dist/renderer.js +40 -29
- package/dist/schema-member-names.d.ts +2 -0
- package/dist/schema-member-names.js +39 -0
- package/dist/schema-scope.d.ts +1 -0
- package/dist/schema-scope.js +29 -16
- package/dist/schema.d.ts +1 -1
- package/dist/sdk.d.ts +2 -1
- package/dist/sdk.js +164 -50
- package/dist/stream.js +24 -23
- package/dist/testing/diagnostic-value.d.ts +1 -0
- package/dist/testing/diagnostic-value.js +57 -0
- package/dist/testing/fakes.js +2 -1
- package/dist/testing/harness.js +1 -0
- package/dist/testing/memory-fs.js +42 -1
- package/dist/testing/parity.js +50 -6
- package/dist/union-validation.d.ts +5 -0
- package/dist/union-validation.js +36 -0
- package/node_modules/@poe-code/process-runner/dist/types.d.ts +2 -0
- package/node_modules/mcp-oauth-server/dist/index.js +47 -6
- package/node_modules/tiny-http-mcp-server/dist/cli.js +14 -2
- package/node_modules/tiny-http-mcp-server/dist/composition.json +1 -1
- package/node_modules/tiny-http-mcp-server/dist/http-server.d.ts +7 -5
- package/node_modules/tiny-http-mcp-server/dist/http-server.js +3 -11
- package/node_modules/tiny-http-mcp-server/dist/http-transport.d.ts +6 -1
- package/node_modules/tiny-http-mcp-server/dist/http-transport.js +196 -15
- package/node_modules/tiny-http-mcp-server/dist/index.d.ts +2 -2
- package/node_modules/tiny-http-mcp-server/dist/modern-headers.d.ts +3 -0
- package/node_modules/tiny-http-mcp-server/dist/modern-headers.js +35 -0
- package/node_modules/tiny-http-mcp-server/dist/parse-body.d.ts +1 -0
- package/node_modules/tiny-http-mcp-server/dist/parse-body.js +9 -5
- package/node_modules/tiny-http-mcp-server/dist/test-support.js +17 -0
- package/node_modules/tiny-http-mcp-server/dist/testing.d.ts +1 -1
- package/node_modules/tiny-http-mcp-server/dist/testing.js +3 -2
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/default-oauth-client-provider.js +21 -4
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/token-endpoint.d.ts +1 -1
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/token-endpoint.js +14 -6
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/http-fetch.d.ts +1 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/http-fetch.js +8 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/http-response.d.ts +1 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/http-response.js +50 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/index.d.ts +2 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/index.js +2 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/server/jwks-token-verifier.js +21 -3
- package/node_modules/tiny-http-mcp-server/package.json +1 -1
- package/node_modules/tiny-mcp-client/README.md +1 -0
- package/node_modules/tiny-mcp-client/dist/index.d.ts +178 -101
- package/node_modules/tiny-mcp-client/dist/index.js +4696 -291
- package/node_modules/tiny-mcp-client/package.json +2 -1
- package/node_modules/tiny-stdio-mcp-server/dist/base64.d.ts +1 -0
- package/node_modules/tiny-stdio-mcp-server/dist/base64.js +5 -0
- package/node_modules/tiny-stdio-mcp-server/dist/composition.json +1 -1
- package/node_modules/tiny-stdio-mcp-server/dist/content/audio.d.ts +3 -0
- package/node_modules/tiny-stdio-mcp-server/dist/content/convert.d.ts +5 -1
- package/node_modules/tiny-stdio-mcp-server/dist/content/convert.js +41 -6
- package/node_modules/tiny-stdio-mcp-server/dist/content/file.d.ts +5 -0
- package/node_modules/tiny-stdio-mcp-server/dist/content/image.d.ts +3 -0
- package/node_modules/tiny-stdio-mcp-server/dist/headers.d.ts +10 -0
- package/node_modules/tiny-stdio-mcp-server/dist/headers.js +180 -0
- package/node_modules/tiny-stdio-mcp-server/dist/index.d.ts +5 -5
- package/node_modules/tiny-stdio-mcp-server/dist/index.js +1 -1
- package/node_modules/tiny-stdio-mcp-server/dist/input-request-schema.d.ts +220 -0
- package/node_modules/tiny-stdio-mcp-server/dist/input-request-schema.js +1995 -0
- package/node_modules/tiny-stdio-mcp-server/dist/jsonrpc.d.ts +1 -0
- package/node_modules/tiny-stdio-mcp-server/dist/jsonrpc.js +38 -25
- package/node_modules/tiny-stdio-mcp-server/dist/metadata.d.ts +2 -0
- package/node_modules/tiny-stdio-mcp-server/dist/metadata.js +37 -0
- package/node_modules/tiny-stdio-mcp-server/dist/protocol-validation.d.ts +4 -0
- package/node_modules/tiny-stdio-mcp-server/dist/protocol-validation.js +53 -0
- package/node_modules/tiny-stdio-mcp-server/dist/protocol.d.ts +17 -0
- package/node_modules/tiny-stdio-mcp-server/dist/protocol.js +228 -0
- package/node_modules/tiny-stdio-mcp-server/dist/request-cancellation.d.ts +1 -0
- package/node_modules/tiny-stdio-mcp-server/dist/request-cancellation.js +18 -0
- package/node_modules/tiny-stdio-mcp-server/dist/sampling-messages.d.ts +18 -0
- package/node_modules/tiny-stdio-mcp-server/dist/sampling-messages.js +34 -0
- package/node_modules/tiny-stdio-mcp-server/dist/schema.d.ts +4 -1
- package/node_modules/tiny-stdio-mcp-server/dist/server.d.ts +9 -4
- package/node_modules/tiny-stdio-mcp-server/dist/server.js +334 -135
- package/node_modules/tiny-stdio-mcp-server/dist/stdio-input.d.ts +3 -0
- package/node_modules/tiny-stdio-mcp-server/dist/stdio-input.js +50 -28
- package/node_modules/tiny-stdio-mcp-server/dist/subscriptions.d.ts +11 -0
- package/node_modules/tiny-stdio-mcp-server/dist/subscriptions.js +128 -0
- package/node_modules/tiny-stdio-mcp-server/dist/types.d.ts +58 -18
- package/node_modules/tiny-stdio-mcp-server/dist/types.js +2 -1
- package/node_modules/tiny-stdio-mcp-server/dist/uri.d.ts +1 -0
- package/node_modules/tiny-stdio-mcp-server/dist/uri.js +41 -0
- package/node_modules/tiny-stdio-mcp-server/package.json +8 -0
- package/node_modules/toolcraft-design/dist/command-registry.d.ts +11 -0
- package/node_modules/toolcraft-design/dist/command-registry.js +24 -0
- package/node_modules/toolcraft-design/dist/dashboard/ansi.d.ts +2 -0
- package/node_modules/toolcraft-design/dist/dashboard/ansi.js +81 -27
- package/node_modules/toolcraft-design/dist/dashboard/buffer.js +39 -25
- package/node_modules/toolcraft-design/dist/dashboard/components/border.js +6 -5
- package/node_modules/toolcraft-design/dist/dashboard/components/footer.js +26 -21
- package/node_modules/toolcraft-design/dist/dashboard/components/output-pane.d.ts +1 -1
- package/node_modules/toolcraft-design/dist/dashboard/components/output-pane.js +12 -6
- package/node_modules/toolcraft-design/dist/dashboard/components/stats-pane.d.ts +2 -1
- package/node_modules/toolcraft-design/dist/dashboard/components/stats-pane.js +51 -10
- package/node_modules/toolcraft-design/dist/dashboard/dashboard.d.ts +4 -0
- package/node_modules/toolcraft-design/dist/dashboard/dashboard.js +77 -4
- package/node_modules/toolcraft-design/dist/dashboard/index.d.ts +2 -0
- package/node_modules/toolcraft-design/dist/dashboard/index.js +2 -0
- package/node_modules/toolcraft-design/dist/dashboard/keymap.js +26 -6
- package/node_modules/toolcraft-design/dist/dashboard/layout.d.ts +1 -0
- package/node_modules/toolcraft-design/dist/dashboard/layout.js +19 -3
- package/node_modules/toolcraft-design/dist/dashboard/line-buffer.d.ts +9 -0
- package/node_modules/toolcraft-design/dist/dashboard/line-buffer.js +63 -0
- package/node_modules/toolcraft-design/dist/dashboard/output-preview.d.ts +9 -0
- package/node_modules/toolcraft-design/dist/dashboard/output-preview.js +70 -0
- package/node_modules/toolcraft-design/dist/dashboard/snapshot.js +3 -1
- package/node_modules/toolcraft-design/dist/dashboard/store.js +9 -3
- package/node_modules/toolcraft-design/dist/dashboard/terminal-strings.d.ts +6 -0
- package/node_modules/toolcraft-design/dist/dashboard/terminal-strings.js +108 -0
- package/node_modules/toolcraft-design/dist/dashboard/terminal-width.js +3 -1
- package/node_modules/toolcraft-design/dist/dashboard/terminal.js +11 -1
- package/node_modules/toolcraft-design/dist/dashboard/testing/pipeline-scenario.d.ts +1 -0
- package/node_modules/toolcraft-design/dist/dashboard/testing/pipeline-scenario.js +126 -0
- package/node_modules/toolcraft-design/dist/dashboard/types.d.ts +3 -1
- package/node_modules/toolcraft-design/dist/event-groups.d.ts +19 -0
- package/node_modules/toolcraft-design/dist/event-groups.js +49 -0
- package/node_modules/toolcraft-design/dist/index.d.ts +6 -1
- package/node_modules/toolcraft-design/dist/index.js +5 -1
- package/node_modules/toolcraft-design/dist/inline-notice.d.ts +14 -0
- package/node_modules/toolcraft-design/dist/inline-notice.js +28 -0
- package/node_modules/toolcraft-design/dist/metric.d.ts +8 -0
- package/node_modules/toolcraft-design/dist/metric.js +21 -0
- package/node_modules/toolcraft-design/dist/overlay-manager.d.ts +6 -0
- package/node_modules/toolcraft-design/dist/overlay-manager.js +10 -0
- package/node_modules/toolcraft-design/dist/primitives.d.ts +12 -0
- package/node_modules/toolcraft-design/dist/primitives.js +7 -0
- package/node_modules/toolcraft-design/dist/progress-group.d.ts +7 -0
- package/node_modules/toolcraft-design/dist/progress-group.js +10 -0
- package/node_modules/toolcraft-design/dist/render-performance.d.ts +33 -0
- package/node_modules/toolcraft-design/dist/render-performance.js +71 -0
- package/node_modules/toolcraft-design/dist/task-tree.d.ts +22 -0
- package/node_modules/toolcraft-design/dist/task-tree.js +79 -0
- package/node_modules/toolcraft-design/dist/viewport.d.ts +18 -0
- package/node_modules/toolcraft-design/dist/viewport.js +56 -0
- package/node_modules/toolcraft-schema/dist/clone-default.d.ts +1 -0
- package/node_modules/toolcraft-schema/dist/clone-default.js +26 -0
- package/node_modules/toolcraft-schema/dist/index.compile-check.js +1 -0
- package/node_modules/toolcraft-schema/dist/index.d.ts +18 -9
- package/node_modules/toolcraft-schema/dist/index.js +46 -8
- package/node_modules/toolcraft-schema/dist/json-schema/compiler.d.ts +1 -0
- package/node_modules/toolcraft-schema/dist/json-schema/compiler.js +6 -0
- package/node_modules/toolcraft-schema/dist/json-schema/evaluate.js +6 -3
- package/node_modules/toolcraft-schema/dist/json-schema/normalize-nullability.d.ts +1 -0
- package/node_modules/toolcraft-schema/dist/json-schema/normalize-nullability.js +69 -0
- package/node_modules/toolcraft-schema/dist/json-schema/types.d.ts +1 -0
- package/node_modules/toolcraft-schema/dist/json.d.ts +4 -1
- package/node_modules/toolcraft-schema/dist/json.js +57 -1
- package/node_modules/toolcraft-schema/dist/native-json-schema.d.ts +10 -0
- package/node_modules/toolcraft-schema/dist/native-json-schema.js +11 -0
- package/node_modules/toolcraft-schema/dist/validate.d.ts +5 -1
- package/node_modules/toolcraft-schema/dist/validate.js +61 -47
- package/node_modules/toolcraft-schema/package.json +1 -1
- package/package.json +6 -3
package/dist/sdk.js
CHANGED
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
import "./node-require-shim.js";
|
|
2
|
+
import { cloneDefaultValue, formatIssues, isJsonValue, isPlainRecord, nativeJsonSchema, unicodeLength, validate as validateSchema } from "toolcraft-schema";
|
|
2
3
|
import { ToolcraftBugError, UserError, assertCommandRequirements, resolveCommandSecrets } from "./index.js";
|
|
3
4
|
import { writeErrorReport } from "./error-report.js";
|
|
4
5
|
import { assertHumanInLoopWired, mergeApprovalsRoot } from "./human-in-loop/wiring.js";
|
|
5
6
|
import { hasMcpProxyGroups, resolveMcpProxies } from "./mcp-proxy.js";
|
|
7
|
+
import { isMCPResult } from "./mcp-result.js";
|
|
6
8
|
import { getExpectedNumberDescription, isValidNumberSchemaValue } from "./number-schema.js";
|
|
9
|
+
import { validateAppliedDefault } from "./applied-default.js";
|
|
7
10
|
import { filterSchemaForScope } from "./schema-scope.js";
|
|
11
|
+
import { validateCasedSchemaMembers } from "./schema-member-names.js";
|
|
8
12
|
import { enableSourceMaps } from "./stack-trim.js";
|
|
9
13
|
import { suggest } from "./suggest.js";
|
|
10
14
|
import { throwValidationErrors } from "./validation-errors.js";
|
|
15
|
+
import { resolveDiscriminatedBranch } from "./discriminator.js";
|
|
16
|
+
import { validateUnionSchema } from "./union-validation.js";
|
|
11
17
|
import { createRuntimeLogger } from "./runtime-logging.js";
|
|
12
18
|
import { createEnv, createFs, validateServices } from "./runtime/io.js";
|
|
13
19
|
import { createManagedStream } from "./stream.js";
|
|
20
|
+
export { mergeApprovalsRoot };
|
|
14
21
|
function splitWords(value) {
|
|
15
22
|
const words = [];
|
|
16
23
|
let current = "";
|
|
@@ -59,9 +66,6 @@ function unwrapOptional(schema) {
|
|
|
59
66
|
function isOptional(schema) {
|
|
60
67
|
return schema.kind === "optional";
|
|
61
68
|
}
|
|
62
|
-
function isPlainObject(value) {
|
|
63
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
64
|
-
}
|
|
65
69
|
function formatAvailableList(values) {
|
|
66
70
|
return `Available: ${[...values].sort().join(", ")}.`;
|
|
67
71
|
}
|
|
@@ -83,15 +87,121 @@ function describeReceived(value) {
|
|
|
83
87
|
if (Array.isArray(value))
|
|
84
88
|
return `array(${value.length})`;
|
|
85
89
|
if (typeof value === "object")
|
|
86
|
-
return "object";
|
|
90
|
+
return isPlainRecord(value) ? "object" : "non-plain object";
|
|
87
91
|
if (typeof value === "string") {
|
|
88
92
|
const s = value.length > 40 ? `${value.slice(0, 40)}…` : value;
|
|
89
93
|
return `${JSON.stringify(s)}`;
|
|
90
94
|
}
|
|
91
|
-
|
|
95
|
+
if (typeof value === "bigint" || typeof value === "symbol" || typeof value === "function") {
|
|
96
|
+
return typeof value;
|
|
97
|
+
}
|
|
98
|
+
return String(value);
|
|
99
|
+
}
|
|
100
|
+
function nativeSDKFields(schema) {
|
|
101
|
+
const shapes = schema.kind === "object" ? [schema.shape]
|
|
102
|
+
: schema.kind === "union" ? schema.branches.map((branch) => branch.shape)
|
|
103
|
+
: schema.kind === "oneOf" ? Object.values(schema.branches).map((branch) => branch.shape) : [];
|
|
104
|
+
return new Map(shapes.flatMap((shape) => Object.entries(shape).map(([key, child]) => [formatSegment(key), [key, child]])));
|
|
105
|
+
}
|
|
106
|
+
function omitNativeOptionalUndefined(schema, value, depth = 0, budget = { nodes: 10_000 }) {
|
|
107
|
+
if (depth > 64 || --budget.nodes < 0)
|
|
108
|
+
return value;
|
|
109
|
+
const canonical = unwrapOptional(schema);
|
|
110
|
+
if (canonical.kind === "array" && Array.isArray(value)) {
|
|
111
|
+
if (value.length > 10_000)
|
|
112
|
+
return value;
|
|
113
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
114
|
+
for (let index = 0; index < value.length; index++) {
|
|
115
|
+
const property = descriptors[String(index)];
|
|
116
|
+
if (property !== undefined && "value" in property) {
|
|
117
|
+
property.value = omitNativeOptionalUndefined(canonical.item, property.value, depth + 1, budget);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const output = Object.defineProperties([], descriptors);
|
|
121
|
+
Object.setPrototypeOf(output, Object.getPrototypeOf(value));
|
|
122
|
+
return output;
|
|
123
|
+
}
|
|
124
|
+
if (canonical.kind === "record" && isPlainRecord(value)) {
|
|
125
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
126
|
+
for (const property of Object.values(descriptors))
|
|
127
|
+
if ("value" in property) {
|
|
128
|
+
property.value = omitNativeOptionalUndefined(canonical.value, property.value, depth + 1, budget);
|
|
129
|
+
}
|
|
130
|
+
return Object.create(Object.getPrototypeOf(value), descriptors);
|
|
131
|
+
}
|
|
132
|
+
if (!isPlainRecord(value) || (canonical.kind !== "object" && canonical.kind !== "union" && canonical.kind !== "oneOf"))
|
|
133
|
+
return value;
|
|
134
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
135
|
+
for (const [inputKey, [, field]] of nativeSDKFields(canonical)) {
|
|
136
|
+
const property = descriptors[inputKey];
|
|
137
|
+
if (property === undefined || !("value" in property))
|
|
138
|
+
continue;
|
|
139
|
+
if (property.value === undefined && isOptional(field))
|
|
140
|
+
delete descriptors[inputKey];
|
|
141
|
+
else
|
|
142
|
+
property.value = omitNativeOptionalUndefined(field, property.value, depth + 1, budget);
|
|
143
|
+
}
|
|
144
|
+
return Object.create(Object.getPrototypeOf(value), descriptors);
|
|
145
|
+
}
|
|
146
|
+
function normalizeNativeSDKKeys(schema, value) {
|
|
147
|
+
const canonical = unwrapOptional(schema);
|
|
148
|
+
if (canonical.kind === "array" && Array.isArray(value)) {
|
|
149
|
+
return value.map((item) => normalizeNativeSDKKeys(canonical.item, item));
|
|
150
|
+
}
|
|
151
|
+
if (canonical.kind === "record" && isPlainRecord(value)) {
|
|
152
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, normalizeNativeSDKKeys(canonical.value, item)]));
|
|
153
|
+
}
|
|
154
|
+
if ((canonical.kind === "object" || canonical.kind === "union" || canonical.kind === "oneOf") && isPlainRecord(value)) {
|
|
155
|
+
const fields = nativeSDKFields(canonical);
|
|
156
|
+
const result = {};
|
|
157
|
+
for (const [key, item] of Object.entries(value)) {
|
|
158
|
+
const field = fields.get(key);
|
|
159
|
+
const outputKey = field?.[0] ?? key;
|
|
160
|
+
if (Object.hasOwn(result, outputKey))
|
|
161
|
+
throw new UserError(`Multiple parameters map to "${outputKey}".`);
|
|
162
|
+
Object.defineProperty(result, outputKey, {
|
|
163
|
+
value: field === undefined ? item : normalizeNativeSDKKeys(field[1], item),
|
|
164
|
+
enumerable: true, configurable: true, writable: true
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
if (canonical.kind === "object") {
|
|
168
|
+
for (const [key, child] of Object.entries(canonical.shape)) {
|
|
169
|
+
const field = unwrapOptional(child);
|
|
170
|
+
if (!Object.hasOwn(result, key) && field.default !== undefined)
|
|
171
|
+
Object.defineProperty(result, key, {
|
|
172
|
+
value: normalizeNativeSDKKeys(field, cloneDefaultValue(field.default)),
|
|
173
|
+
enumerable: true, configurable: true, writable: true
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return result;
|
|
178
|
+
}
|
|
179
|
+
return value;
|
|
180
|
+
}
|
|
181
|
+
function validateNativeSDKValue(schema, value, label, errors) {
|
|
182
|
+
value = omitNativeOptionalUndefined(schema, value);
|
|
183
|
+
if (!isJsonValue(value)) {
|
|
184
|
+
errors.push({ path: label, message: `Invalid value for "${label}". Expected a JSON value.` });
|
|
185
|
+
return value;
|
|
186
|
+
}
|
|
187
|
+
const normalized = normalizeNativeSDKKeys(schema, value);
|
|
188
|
+
const validation = validateSchema(schema, normalized);
|
|
189
|
+
if (!validation.ok) {
|
|
190
|
+
errors.push(...validation.issues.map((issue) => ({
|
|
191
|
+
path: [label, ...issue.path].filter((part) => part !== "").join("."),
|
|
192
|
+
message: formatIssues([issue])
|
|
193
|
+
})));
|
|
194
|
+
}
|
|
195
|
+
return normalized;
|
|
92
196
|
}
|
|
93
197
|
function validateSchemaValue(schema, value, label, errors) {
|
|
94
198
|
const unwrappedSchema = unwrapOptional(schema);
|
|
199
|
+
if (isOptional(schema) && value === undefined) {
|
|
200
|
+
return validateAppliedDefault(unwrappedSchema, label, errors);
|
|
201
|
+
}
|
|
202
|
+
if (unwrappedSchema[nativeJsonSchema] !== undefined) {
|
|
203
|
+
return validateNativeSDKValue(unwrappedSchema, value, label, errors);
|
|
204
|
+
}
|
|
95
205
|
if (value === null && unwrappedSchema.nullable === true) {
|
|
96
206
|
return null;
|
|
97
207
|
}
|
|
@@ -137,13 +247,23 @@ function validateSchemaValue(schema, value, label, errors) {
|
|
|
137
247
|
return value;
|
|
138
248
|
}
|
|
139
249
|
validateArrayConstraints(unwrappedSchema, value, label, errors);
|
|
140
|
-
return value.
|
|
250
|
+
return Array.from({ length: value.length }, (_item, index) => validateSchemaValue(unwrappedSchema.item, value[index], `${label}[${index}]`, errors));
|
|
141
251
|
case "object":
|
|
142
252
|
return validateObjectSchema(unwrappedSchema, value, label, errors);
|
|
143
|
-
case "json":
|
|
253
|
+
case "json": {
|
|
254
|
+
const validation = validateSchema(unwrappedSchema, value);
|
|
255
|
+
if (!validation.ok) {
|
|
256
|
+
for (const issue of validation.issues) {
|
|
257
|
+
errors.push({
|
|
258
|
+
path: label,
|
|
259
|
+
message: `Invalid value for "${label}". Expected a JSON value, got ${issue.received}.`
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
}
|
|
144
263
|
return value;
|
|
264
|
+
}
|
|
145
265
|
case "record": {
|
|
146
|
-
if (!
|
|
266
|
+
if (!isPlainRecord(value)) {
|
|
147
267
|
errors.push({
|
|
148
268
|
path: label,
|
|
149
269
|
message: `Invalid value for "${label}". Expected an object, got ${describeReceived(value)}.`
|
|
@@ -156,42 +276,32 @@ function validateSchemaValue(schema, value, label, errors) {
|
|
|
156
276
|
]));
|
|
157
277
|
}
|
|
158
278
|
case "oneOf": {
|
|
159
|
-
|
|
279
|
+
const resolved = resolveDiscriminatedBranch(unwrappedSchema, value, formatSegment(unwrappedSchema.discriminator), label, errors);
|
|
280
|
+
if (resolved === undefined) {
|
|
160
281
|
return value;
|
|
161
282
|
}
|
|
162
|
-
const discriminator = value[unwrappedSchema.discriminator];
|
|
163
|
-
const branch = typeof discriminator === "string" ? unwrappedSchema.branches[discriminator] : undefined;
|
|
164
|
-
if (branch === undefined) {
|
|
165
|
-
return value;
|
|
166
|
-
}
|
|
167
|
-
const { [unwrappedSchema.discriminator]: ignoredDiscriminator, ...branchValue } = value;
|
|
168
|
-
void ignoredDiscriminator;
|
|
169
283
|
return {
|
|
170
|
-
|
|
171
|
-
|
|
284
|
+
...validateObjectSchema(resolved.branch, resolved.value, label, errors),
|
|
285
|
+
[unwrappedSchema.discriminator]: resolved.discriminator
|
|
172
286
|
};
|
|
173
287
|
}
|
|
174
288
|
case "union": {
|
|
175
|
-
|
|
176
|
-
return value;
|
|
177
|
-
}
|
|
178
|
-
const branch = unwrappedSchema.branches.find((candidate) => Object.keys(candidate.shape).every((key) => candidate.shape[key]?.kind === "optional" ||
|
|
179
|
-
Object.prototype.hasOwnProperty.call(value, formatSegment(key))));
|
|
180
|
-
return branch === undefined ? value : validateObjectSchema(branch, value, label, errors);
|
|
289
|
+
return validateUnionSchema(unwrappedSchema, value, label, errors, (branch, branchErrors) => validateObjectSchema(branch, value, label, branchErrors));
|
|
181
290
|
}
|
|
182
291
|
}
|
|
183
292
|
}
|
|
184
293
|
function validateStringConstraints(schema, value, label, errors) {
|
|
185
|
-
|
|
294
|
+
const length = unicodeLength(value);
|
|
295
|
+
if (schema.minLength !== undefined && length < schema.minLength) {
|
|
186
296
|
errors.push({
|
|
187
297
|
path: label,
|
|
188
|
-
message: `Invalid value for "${label}". Expected a string with length at least ${schema.minLength}, got string with length ${
|
|
298
|
+
message: `Invalid value for "${label}". Expected a string with length at least ${schema.minLength}, got string with length ${length}.`
|
|
189
299
|
});
|
|
190
300
|
}
|
|
191
|
-
if (schema.maxLength !== undefined &&
|
|
301
|
+
if (schema.maxLength !== undefined && length > schema.maxLength) {
|
|
192
302
|
errors.push({
|
|
193
303
|
path: label,
|
|
194
|
-
message: `Invalid value for "${label}". Expected a string with length at most ${schema.maxLength}, got string with length ${
|
|
304
|
+
message: `Invalid value for "${label}". Expected a string with length at most ${schema.maxLength}, got string with length ${length}.`
|
|
195
305
|
});
|
|
196
306
|
}
|
|
197
307
|
if (schema.pattern !== undefined && !new RegExp(schema.pattern).test(value)) {
|
|
@@ -216,7 +326,10 @@ function validateArrayConstraints(schema, value, label, errors) {
|
|
|
216
326
|
}
|
|
217
327
|
}
|
|
218
328
|
export function validateObjectSchema(schema, value, label, errors) {
|
|
219
|
-
if (
|
|
329
|
+
if (schema[nativeJsonSchema] !== undefined) {
|
|
330
|
+
return validateNativeSDKValue(schema, value, label, errors);
|
|
331
|
+
}
|
|
332
|
+
if (!isPlainRecord(value)) {
|
|
220
333
|
errors.push({
|
|
221
334
|
path: label,
|
|
222
335
|
message: `Invalid value for "${label}". Expected an object, got ${describeReceived(value)}.`
|
|
@@ -250,10 +363,10 @@ export function validateObjectSchema(schema, value, label, errors) {
|
|
|
250
363
|
const childSchema = unwrapOptional(rawChildSchema);
|
|
251
364
|
const hasValue = Object.prototype.hasOwnProperty.call(value, inputKey);
|
|
252
365
|
const fieldLabel = label.length === 0 ? inputKey : `${label}.${inputKey}`;
|
|
253
|
-
if (!hasValue) {
|
|
366
|
+
if (!hasValue || (isOptional(rawChildSchema) && value[inputKey] === undefined)) {
|
|
254
367
|
if (childSchema.default !== undefined) {
|
|
255
368
|
Object.defineProperty(result, outputKey, {
|
|
256
|
-
value: childSchema
|
|
369
|
+
value: validateAppliedDefault(childSchema, fieldLabel, errors),
|
|
257
370
|
enumerable: true,
|
|
258
371
|
configurable: true,
|
|
259
372
|
writable: true
|
|
@@ -261,6 +374,13 @@ export function validateObjectSchema(schema, value, label, errors) {
|
|
|
261
374
|
continue;
|
|
262
375
|
}
|
|
263
376
|
if (isOptional(rawChildSchema)) {
|
|
377
|
+
if (inputKey !== outputKey && Object.hasOwn(result, outputKey)) {
|
|
378
|
+
const aliasLabel = label.length === 0 ? outputKey : `${label}.${outputKey}`;
|
|
379
|
+
errors.push({
|
|
380
|
+
path: aliasLabel,
|
|
381
|
+
message: `Unexpected parameter "${aliasLabel}". Use "${fieldLabel}" for this declared parameter.`
|
|
382
|
+
});
|
|
383
|
+
}
|
|
264
384
|
continue;
|
|
265
385
|
}
|
|
266
386
|
errors.push({ path: fieldLabel, message: `Missing required parameter "${fieldLabel}".` });
|
|
@@ -275,21 +395,6 @@ export function validateObjectSchema(schema, value, label, errors) {
|
|
|
275
395
|
}
|
|
276
396
|
return result;
|
|
277
397
|
}
|
|
278
|
-
function validateUniqueSDKParameterMembers(schema) {
|
|
279
|
-
const sourceKeysByMember = new Map();
|
|
280
|
-
for (const [key, rawChildSchema] of Object.entries(schema.shape)) {
|
|
281
|
-
const member = formatSegment(key);
|
|
282
|
-
const existingKey = sourceKeysByMember.get(member);
|
|
283
|
-
if (existingKey !== undefined) {
|
|
284
|
-
throw new UserError(`Parameters "${existingKey}" and "${key}" use conflicting SDK member "${member}".`);
|
|
285
|
-
}
|
|
286
|
-
sourceKeysByMember.set(member, key);
|
|
287
|
-
const childSchema = unwrapOptional(rawChildSchema);
|
|
288
|
-
if (childSchema.kind === "object") {
|
|
289
|
-
validateUniqueSDKParameterMembers(childSchema);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
398
|
function validateSDKArguments(schema, argumentsValue) {
|
|
294
399
|
const errors = [];
|
|
295
400
|
const result = validateObjectSchema(schema, argumentsValue ?? {}, "", errors);
|
|
@@ -330,7 +435,7 @@ function createResolvedSDK(root, options = {}) {
|
|
|
330
435
|
if (node.kind === "command") {
|
|
331
436
|
const sdkParamsSchema = filterSchemaForScope(node.params, "sdk");
|
|
332
437
|
if (sdkParamsSchema?.kind === "object") {
|
|
333
|
-
|
|
438
|
+
validateCasedSchemaMembers(sdkParamsSchema, formatSegment, "SDK member");
|
|
334
439
|
}
|
|
335
440
|
if (node.stream !== undefined) {
|
|
336
441
|
return (params, streamOptions = {}) => createManagedStream({
|
|
@@ -419,9 +524,15 @@ function createResolvedSDK(root, options = {}) {
|
|
|
419
524
|
...baseContext,
|
|
420
525
|
params: validatedParams
|
|
421
526
|
};
|
|
422
|
-
|
|
527
|
+
const result = humanInLoop === undefined
|
|
423
528
|
? await node.handler(handlerContext)
|
|
424
529
|
: await humanInLoop.invoke(node, handlerContext, commandPath);
|
|
530
|
+
if (node.result !== undefined && isMCPResult(result) && result.isError === true) {
|
|
531
|
+
const text = result.content.flatMap((block) => block.type === "text" ? [block.text] : []).join("\n");
|
|
532
|
+
const message = text || (result.structuredContent === undefined ? "Upstream tool failed." : JSON.stringify(result.structuredContent));
|
|
533
|
+
throw new UserError(message, { cause: result });
|
|
534
|
+
}
|
|
535
|
+
return result;
|
|
425
536
|
}
|
|
426
537
|
catch (error) {
|
|
427
538
|
await writeErrorReport({
|
|
@@ -451,7 +562,7 @@ function createResolvedSDK(root, options = {}) {
|
|
|
451
562
|
}
|
|
452
563
|
else {
|
|
453
564
|
childValue = build(child, nextPath);
|
|
454
|
-
if (!
|
|
565
|
+
if (!isPlainRecord(childValue) || Object.keys(childValue).length === 0) {
|
|
455
566
|
continue;
|
|
456
567
|
}
|
|
457
568
|
}
|
|
@@ -476,7 +587,10 @@ function createDeferredSDK(root, options) {
|
|
|
476
587
|
sdkPromise ??= (async () => {
|
|
477
588
|
await resolveMcpProxies(root, { projectRoot: options.projectRoot });
|
|
478
589
|
return createResolvedSDK(root, options);
|
|
479
|
-
})()
|
|
590
|
+
})().catch((error) => {
|
|
591
|
+
sdkPromise = undefined;
|
|
592
|
+
throw error;
|
|
593
|
+
});
|
|
480
594
|
return sdkPromise;
|
|
481
595
|
};
|
|
482
596
|
const resolvePath = async (path) => {
|
package/dist/stream.js
CHANGED
|
@@ -6,39 +6,32 @@ function validationMessage(schema, value) {
|
|
|
6
6
|
}
|
|
7
7
|
export function createManagedStream(options) {
|
|
8
8
|
const controller = new AbortController();
|
|
9
|
-
let iterator;
|
|
10
9
|
let iteratorPromise;
|
|
11
10
|
let closePromise;
|
|
12
11
|
let done = false;
|
|
13
|
-
const getIterator =
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
iteratorPromise ??= options
|
|
18
|
-
.create(controller.signal, (event) => options.onStatus?.(event))
|
|
12
|
+
const getIterator = () => {
|
|
13
|
+
iteratorPromise ??= Promise.resolve()
|
|
14
|
+
.then(() => options.create(controller.signal, (event) => options.onStatus?.(event)))
|
|
19
15
|
.then((iterable) => iterable[Symbol.asyncIterator]());
|
|
20
|
-
|
|
21
|
-
return iterator;
|
|
16
|
+
return iteratorPromise;
|
|
22
17
|
};
|
|
23
|
-
const close =
|
|
18
|
+
const close = (reason) => {
|
|
24
19
|
if (closePromise !== undefined) {
|
|
25
20
|
return closePromise;
|
|
26
21
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
await activeIterator.return?.();
|
|
37
|
-
})();
|
|
22
|
+
const closingIterator = done ? undefined : iteratorPromise;
|
|
23
|
+
done = true;
|
|
24
|
+
options.signal?.removeEventListener("abort", abortFromConsumer);
|
|
25
|
+
closePromise = closingIterator === undefined
|
|
26
|
+
? Promise.resolve()
|
|
27
|
+
: closingIterator.then(async (activeIterator) => {
|
|
28
|
+
await activeIterator.return?.();
|
|
29
|
+
}, () => undefined);
|
|
30
|
+
controller.abort(reason);
|
|
38
31
|
return closePromise;
|
|
39
32
|
};
|
|
40
33
|
const abortFromConsumer = () => {
|
|
41
|
-
void close(options.signal?.reason);
|
|
34
|
+
void close(options.signal?.reason).catch(() => undefined);
|
|
42
35
|
};
|
|
43
36
|
if (options.signal?.aborted === true) {
|
|
44
37
|
abortFromConsumer();
|
|
@@ -56,15 +49,23 @@ export function createManagedStream(options) {
|
|
|
56
49
|
await close(controller.signal.reason);
|
|
57
50
|
return { done: true, value: undefined };
|
|
58
51
|
}
|
|
59
|
-
const activeIterator = await getIterator();
|
|
60
52
|
let result;
|
|
61
53
|
try {
|
|
54
|
+
const activeIterator = await getIterator();
|
|
55
|
+
if (done || controller.signal.aborted) {
|
|
56
|
+
await close(controller.signal.reason);
|
|
57
|
+
return { done: true, value: undefined };
|
|
58
|
+
}
|
|
62
59
|
result = await activeIterator.next();
|
|
63
60
|
}
|
|
64
61
|
catch (error) {
|
|
65
62
|
await close(error);
|
|
66
63
|
throw error;
|
|
67
64
|
}
|
|
65
|
+
if (controller.signal.aborted) {
|
|
66
|
+
await close(controller.signal.reason);
|
|
67
|
+
return { done: true, value: undefined };
|
|
68
|
+
}
|
|
68
69
|
if (result.done === true) {
|
|
69
70
|
done = true;
|
|
70
71
|
options.signal?.removeEventListener("abort", abortFromConsumer);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function formatDiagnosticValue(value: unknown): string;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { types } from "node:util";
|
|
2
|
+
export function formatDiagnosticValue(value) {
|
|
3
|
+
const ancestors = new WeakSet();
|
|
4
|
+
let remaining = 100;
|
|
5
|
+
function render(current, depth) {
|
|
6
|
+
if (remaining <= 0)
|
|
7
|
+
return "…";
|
|
8
|
+
remaining -= 1;
|
|
9
|
+
if (current === null)
|
|
10
|
+
return "null";
|
|
11
|
+
if (current === undefined)
|
|
12
|
+
return "undefined";
|
|
13
|
+
if (typeof current === "string") {
|
|
14
|
+
return JSON.stringify(current.length > 1000 ? `${current.slice(0, 1000)}…` : current);
|
|
15
|
+
}
|
|
16
|
+
if (typeof current === "function")
|
|
17
|
+
return "[Function]";
|
|
18
|
+
if (typeof current === "bigint")
|
|
19
|
+
return `${current}n`;
|
|
20
|
+
if (typeof current !== "object")
|
|
21
|
+
return Object.is(current, -0) ? "-0" : String(current);
|
|
22
|
+
if (types.isProxy(current))
|
|
23
|
+
return "[Proxy]";
|
|
24
|
+
if (ancestors.has(current))
|
|
25
|
+
return "[Circular]";
|
|
26
|
+
const array = Array.isArray(current);
|
|
27
|
+
if (depth >= 4)
|
|
28
|
+
return array ? "[Array]" : "[Object]";
|
|
29
|
+
const keys = array
|
|
30
|
+
? Array.from({ length: Math.min(current.length, 25) }, (_value, index) => String(index))
|
|
31
|
+
: Object.keys(current);
|
|
32
|
+
const count = array ? current.length : keys.length;
|
|
33
|
+
ancestors.add(current);
|
|
34
|
+
try {
|
|
35
|
+
const entries = keys.slice(0, 25).map((key) => {
|
|
36
|
+
const descriptor = Object.getOwnPropertyDescriptor(current, key);
|
|
37
|
+
const rendered = descriptor === undefined
|
|
38
|
+
? "[Empty]"
|
|
39
|
+
: "value" in descriptor ? render(descriptor.value, depth + 1) : "[Accessor]";
|
|
40
|
+
return array ? rendered : `${JSON.stringify(key)}:${rendered}`;
|
|
41
|
+
});
|
|
42
|
+
if (count > entries.length)
|
|
43
|
+
entries.push("…");
|
|
44
|
+
return array ? `[${entries.join(",")}]` : `{${entries.join(",")}}`;
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
ancestors.delete(current);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
const rendered = render(value, 0);
|
|
52
|
+
return rendered.length > 4000 ? `${rendered.slice(0, 4000)}…` : rendered;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return "[Uninspectable]";
|
|
56
|
+
}
|
|
57
|
+
}
|
package/dist/testing/fakes.js
CHANGED
|
@@ -11,7 +11,7 @@ export function fakeService(stubs = {}) {
|
|
|
11
11
|
}
|
|
12
12
|
const stub = Reflect.get(target, property, receiver);
|
|
13
13
|
if (typeof stub !== "function") {
|
|
14
|
-
if (stub !== undefined) {
|
|
14
|
+
if (stub !== undefined || property === "then") {
|
|
15
15
|
return stub;
|
|
16
16
|
}
|
|
17
17
|
return (...args) => {
|
|
@@ -63,6 +63,7 @@ export function fakeFetch(routes) {
|
|
|
63
63
|
const fetch = async (input, init) => {
|
|
64
64
|
const request = new Request(input, init);
|
|
65
65
|
calls.push(request);
|
|
66
|
+
request.signal.throwIfAborted();
|
|
66
67
|
const route = routes.find((candidate) => routeMatches(candidate, request));
|
|
67
68
|
if (route === undefined) {
|
|
68
69
|
const configuredRoutes = routes.map(routeDescription).join(", ") || "none";
|
package/dist/testing/harness.js
CHANGED
|
@@ -199,6 +199,7 @@ export function createCommandTestHarness(root, options = {}) {
|
|
|
199
199
|
env: Object.fromEntries(Object.entries(options.env ?? {}).flatMap(([key, value]) => value === undefined ? [] : [[key, value]])),
|
|
200
200
|
fs: memoryFs,
|
|
201
201
|
fetch: runtimeFetch,
|
|
202
|
+
apiVersion: options.apiVersion,
|
|
202
203
|
logLevel: options.logLevel,
|
|
203
204
|
outputEmitter(entry) {
|
|
204
205
|
stdout += entry;
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
const writeModes = new Map([
|
|
2
|
+
...["r", "rs", "sr"].map((flag) => [flag, "read"]),
|
|
3
|
+
...["r+", "rs+", "sr+"].map((flag) => [flag, "update"]),
|
|
4
|
+
...["w", "w+", "wx", "xw", "wx+", "xw+"].map((flag) => [flag, "replace"]),
|
|
5
|
+
...["a", "a+", "ax", "xa", "ax+", "xa+", "as", "sa", "as+", "sa+"].map((flag) => [flag, "append"])
|
|
6
|
+
]);
|
|
1
7
|
function missingFileError(syscall, path, dest) {
|
|
2
8
|
const target = dest === undefined ? `'${path}'` : `'${path}' -> '${dest}'`;
|
|
3
9
|
const error = new Error(`ENOENT: no such file or directory, ${syscall} ${target}`);
|
|
@@ -22,7 +28,42 @@ export function createMemoryFs(files = {}) {
|
|
|
22
28
|
return value.toString(encoding);
|
|
23
29
|
},
|
|
24
30
|
async writeFile(path, value, options) {
|
|
25
|
-
|
|
31
|
+
const bytes = Buffer.from(value, options?.encoding ?? "utf8");
|
|
32
|
+
const flag = options?.flag || "w";
|
|
33
|
+
const mode = writeModes.get(flag);
|
|
34
|
+
if (mode === undefined) {
|
|
35
|
+
throw Object.assign(new TypeError(`The argument 'flags' is invalid. Received '${flag}'`), {
|
|
36
|
+
code: "ERR_INVALID_ARG_VALUE"
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
const previous = contents.get(path);
|
|
40
|
+
if (flag.includes("x") && previous !== undefined) {
|
|
41
|
+
throw Object.assign(new Error(`EEXIST: file already exists, open '${path}'`), {
|
|
42
|
+
code: "EEXIST",
|
|
43
|
+
errno: -17,
|
|
44
|
+
syscall: "open",
|
|
45
|
+
path
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
if ((mode === "read" || mode === "update") && previous === undefined) {
|
|
49
|
+
throw missingFileError("open", path);
|
|
50
|
+
}
|
|
51
|
+
if (mode === "read" && bytes.length > 0) {
|
|
52
|
+
throw Object.assign(new Error("EBADF: bad file descriptor, write"), {
|
|
53
|
+
code: "EBADF",
|
|
54
|
+
errno: -9,
|
|
55
|
+
syscall: "write"
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
if (mode === "append" && previous !== undefined) {
|
|
59
|
+
contents.set(path, Buffer.concat([previous, bytes]));
|
|
60
|
+
}
|
|
61
|
+
else if (mode === "update" && previous !== undefined) {
|
|
62
|
+
contents.set(path, Buffer.concat([bytes, previous.subarray(bytes.length)]));
|
|
63
|
+
}
|
|
64
|
+
else if (mode !== "read") {
|
|
65
|
+
contents.set(path, bytes);
|
|
66
|
+
}
|
|
26
67
|
changeLog.push({ op: "writeFile", path });
|
|
27
68
|
},
|
|
28
69
|
async exists(path) {
|
package/dist/testing/parity.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { isDeepStrictEqual } from "node:util";
|
|
1
|
+
import { isDeepStrictEqual, types } from "node:util";
|
|
2
2
|
import { McpClient, McpError, ERROR_INVALID_PARAMS, createSdkTestPair } from "tiny-mcp-client";
|
|
3
3
|
import { runCLI } from "../cli.js";
|
|
4
4
|
import { UserError } from "../index.js";
|
|
5
5
|
import { createMCPServer } from "../mcp.js";
|
|
6
6
|
import { filterSchemaForScope } from "../schema-scope.js";
|
|
7
7
|
import { createSDK } from "../sdk.js";
|
|
8
|
+
import { formatDiagnosticValue } from "./diagnostic-value.js";
|
|
8
9
|
class SurfaceScopeError extends Error {
|
|
9
10
|
constructor(surface, path) {
|
|
10
11
|
super(`Command "${path.join(" ")}" is filtered out of the ${surface} surface.`);
|
|
@@ -338,11 +339,53 @@ async function runCLISurface(root, resolved, params, options, reference) {
|
|
|
338
339
|
process.exitCode = previousExitCode;
|
|
339
340
|
}
|
|
340
341
|
}
|
|
342
|
+
const domExceptionMessageGetter = typeof DOMException === "undefined"
|
|
343
|
+
? undefined
|
|
344
|
+
: Object.getOwnPropertyDescriptor(DOMException.prototype, "message")?.get;
|
|
345
|
+
function nativeDOMExceptionMessage(error) {
|
|
346
|
+
if (typeof error !== "object" || error === null || types.isProxy(error))
|
|
347
|
+
return undefined;
|
|
348
|
+
try {
|
|
349
|
+
return domExceptionMessageGetter?.call(error);
|
|
350
|
+
}
|
|
351
|
+
catch {
|
|
352
|
+
return undefined;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
function propertyDescriptor(value, name) {
|
|
356
|
+
let current = value;
|
|
357
|
+
while (current !== null &&
|
|
358
|
+
(typeof current === "object" || typeof current === "function") &&
|
|
359
|
+
!types.isProxy(current)) {
|
|
360
|
+
const descriptor = Object.getOwnPropertyDescriptor(current, name);
|
|
361
|
+
if (descriptor !== undefined)
|
|
362
|
+
return descriptor;
|
|
363
|
+
current = Object.getPrototypeOf(current);
|
|
364
|
+
}
|
|
365
|
+
return undefined;
|
|
366
|
+
}
|
|
341
367
|
function errorIdentity(error) {
|
|
342
|
-
|
|
343
|
-
|
|
368
|
+
const domMessage = nativeDOMExceptionMessage(error);
|
|
369
|
+
if (types.isNativeError(error) || domMessage !== undefined) {
|
|
370
|
+
const prototype = Object.getPrototypeOf(error);
|
|
371
|
+
const constructor = propertyDescriptor(prototype, "constructor")?.value;
|
|
372
|
+
const name = typeof constructor === "function" && !types.isProxy(constructor)
|
|
373
|
+
? Object.getOwnPropertyDescriptor(constructor, "name")?.value
|
|
374
|
+
: undefined;
|
|
375
|
+
const descriptor = propertyDescriptor(error, "message");
|
|
376
|
+
const message = descriptor === undefined
|
|
377
|
+
? ""
|
|
378
|
+
: "value" in descriptor
|
|
379
|
+
? typeof descriptor.value === "string" ? descriptor.value : formatDiagnosticValue(descriptor.value)
|
|
380
|
+
: descriptor.get === domExceptionMessageGetter && domMessage !== undefined
|
|
381
|
+
? domMessage
|
|
382
|
+
: "[Accessor]";
|
|
383
|
+
return { name: typeof name === "string" ? name : "Error", message };
|
|
344
384
|
}
|
|
345
|
-
return {
|
|
385
|
+
return {
|
|
386
|
+
name: typeof error,
|
|
387
|
+
message: typeof error === "string" ? error : formatDiagnosticValue(error)
|
|
388
|
+
};
|
|
346
389
|
}
|
|
347
390
|
function outcomesAgree(left, right) {
|
|
348
391
|
if (left.ok !== right.ok) {
|
|
@@ -355,10 +398,11 @@ function outcomesAgree(left, right) {
|
|
|
355
398
|
}
|
|
356
399
|
function describeOutcome(surface, outcome) {
|
|
357
400
|
if (outcome.ok) {
|
|
358
|
-
return `${surface}: ok ${
|
|
401
|
+
return `${surface}: ok ${formatDiagnosticValue(outcome.value)}`;
|
|
359
402
|
}
|
|
360
403
|
const error = errorIdentity(outcome.error);
|
|
361
|
-
|
|
404
|
+
const description = `${surface}: error ${error.name}: ${error.message}`;
|
|
405
|
+
return description.length > 4000 ? `${description.slice(0, 4000)}…` : description;
|
|
362
406
|
}
|
|
363
407
|
export async function runParity(root, resolved, params, options) {
|
|
364
408
|
const sdk = await runSDK(root, resolved, params, options);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type AnySchema, type ObjectSchema } from "toolcraft-schema";
|
|
2
|
+
import type { ValidationError } from "./validation-errors.js";
|
|
3
|
+
export declare function validateUnionSchema(schema: Extract<AnySchema, {
|
|
4
|
+
kind: "union";
|
|
5
|
+
}>, value: unknown, label: string, errors: ValidationError[], validateBranch: (branch: ObjectSchema<any>, branchErrors: ValidationError[]) => Record<string, unknown>): unknown;
|