@paretools/shared 0.21.1 → 0.22.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/dist/compact.d.ts +128 -0
- package/dist/compact.d.ts.map +1 -0
- package/dist/compact.js +130 -0
- package/dist/compact.js.map +1 -0
- package/dist/diagnostics.d.ts +75 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +70 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/testing.d.ts +25 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +56 -0
- package/dist/testing.js.map +1 -0
- package/package.json +7 -3
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Default number of leading lines kept when truncating a stream for compact
|
|
4
|
+
* output. Matches the budget introduced for `server-process` in PR #1020.
|
|
5
|
+
*/
|
|
6
|
+
export declare const COMPACT_HEAD_LINES = 40;
|
|
7
|
+
/**
|
|
8
|
+
* Default number of trailing lines kept when truncating a stream for compact
|
|
9
|
+
* output. Matches the budget introduced for `server-process` in PR #1020.
|
|
10
|
+
*/
|
|
11
|
+
export declare const COMPACT_TAIL_LINES = 10;
|
|
12
|
+
/**
|
|
13
|
+
* Default hard byte cap applied to each stream after line trimming.
|
|
14
|
+
* Matches the budget introduced for `server-process` in PR #1020.
|
|
15
|
+
*/
|
|
16
|
+
export declare const COMPACT_BYTE_CAP = 8192;
|
|
17
|
+
/** Options for {@link truncateStream} and {@link compactStreamFields}. */
|
|
18
|
+
export interface TruncateStreamOptions {
|
|
19
|
+
/** Number of leading lines to keep (default {@link COMPACT_HEAD_LINES}). */
|
|
20
|
+
headLines?: number;
|
|
21
|
+
/** Number of trailing lines to keep (default {@link COMPACT_TAIL_LINES}). */
|
|
22
|
+
tailLines?: number;
|
|
23
|
+
/** Hard byte cap applied after line trimming (default {@link COMPACT_BYTE_CAP}). */
|
|
24
|
+
byteCap?: number;
|
|
25
|
+
}
|
|
26
|
+
/** Result of {@link truncateStream}. */
|
|
27
|
+
export interface TruncateStreamResult {
|
|
28
|
+
/** The (possibly truncated) text. */
|
|
29
|
+
text: string;
|
|
30
|
+
/** Whether any truncation (line trimming or byte cap) occurred. */
|
|
31
|
+
truncated: boolean;
|
|
32
|
+
/** Total number of lines in the original text (before truncation). */
|
|
33
|
+
totalLines: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Truncates a stream (stdout/stderr) to a compact budget: the first
|
|
37
|
+
* `headLines` lines and the last `tailLines` lines with a
|
|
38
|
+
* `... (N lines omitted) ...` marker in between, followed by a hard byte cap
|
|
39
|
+
* that appends `... (truncated)` when exceeded.
|
|
40
|
+
*
|
|
41
|
+
* Behaviorally identical to the compact truncation shipped for
|
|
42
|
+
* `server-process` in PR #1020, extracted so every server can share it
|
|
43
|
+
* (epic #1022).
|
|
44
|
+
*
|
|
45
|
+
* Notes:
|
|
46
|
+
* - Lines are split on `"\n"`; CRLF input keeps its `"\r"` characters and a
|
|
47
|
+
* trailing newline counts as one extra (empty) line, mirroring the
|
|
48
|
+
* reference implementation.
|
|
49
|
+
* - The byte cap is applied to the JavaScript string length (UTF-16 code
|
|
50
|
+
* units), matching the original implementation.
|
|
51
|
+
*
|
|
52
|
+
* @param text - The raw stream text to truncate.
|
|
53
|
+
* @param opts - Optional budget overrides (see {@link TruncateStreamOptions}).
|
|
54
|
+
* @returns The truncated text, whether truncation occurred, and the total
|
|
55
|
+
* line count of the original text.
|
|
56
|
+
*/
|
|
57
|
+
export declare function truncateStream(text: string, opts?: TruncateStreamOptions): TruncateStreamResult;
|
|
58
|
+
/**
|
|
59
|
+
* The optional stdout/stderr fields produced by {@link compactStreamFields}.
|
|
60
|
+
*
|
|
61
|
+
* Truncation flags are only present (and always `true`) when the
|
|
62
|
+
* corresponding stream was truncated; total line counts are only present
|
|
63
|
+
* alongside their flag. Empty streams are omitted entirely.
|
|
64
|
+
*/
|
|
65
|
+
export interface CompactStreamFields {
|
|
66
|
+
/** Truncated stdout (omitted when the stream is empty). */
|
|
67
|
+
stdout?: string;
|
|
68
|
+
/** Truncated stderr (omitted when the stream is empty). */
|
|
69
|
+
stderr?: string;
|
|
70
|
+
/** Present (and `true`) only when stdout was truncated. */
|
|
71
|
+
stdoutTruncated?: true;
|
|
72
|
+
/** Present (and `true`) only when stderr was truncated. */
|
|
73
|
+
stderrTruncated?: true;
|
|
74
|
+
/** Total stdout lines before truncation; present only when stdoutTruncated. */
|
|
75
|
+
stdoutTotalLines?: number;
|
|
76
|
+
/** Total stderr lines before truncation; present only when stderrTruncated. */
|
|
77
|
+
stderrTotalLines?: number;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Builds the compact stdout/stderr field set used by compact tool results.
|
|
81
|
+
*
|
|
82
|
+
* Convenience wrapper around {@link truncateStream} producing the exact
|
|
83
|
+
* optional-field shape shipped for `server-process` in PR #1020:
|
|
84
|
+
*
|
|
85
|
+
* - Empty or `undefined` streams are omitted entirely (no `stdout: ""`).
|
|
86
|
+
* - `stdoutTruncated`/`stderrTruncated` are set (to `true`) only when the
|
|
87
|
+
* corresponding stream was actually truncated — never `false`.
|
|
88
|
+
* - `stdoutTotalLines`/`stderrTotalLines` are set only when the
|
|
89
|
+
* corresponding truncated flag is set.
|
|
90
|
+
*
|
|
91
|
+
* Spread the result into a compact result object:
|
|
92
|
+
* ```ts
|
|
93
|
+
* const compact = { exitCode, success, ...compactStreamFields(stdout, stderr) };
|
|
94
|
+
* ```
|
|
95
|
+
*
|
|
96
|
+
* @param stdout - Raw stdout text (empty/undefined streams are omitted).
|
|
97
|
+
* @param stderr - Raw stderr text (empty/undefined streams are omitted).
|
|
98
|
+
* @param opts - Optional budget overrides (see {@link TruncateStreamOptions}).
|
|
99
|
+
* @returns An object containing only the fields that apply.
|
|
100
|
+
*/
|
|
101
|
+
export declare function compactStreamFields(stdout: string | undefined, stderr: string | undefined, opts?: TruncateStreamOptions): CompactStreamFields;
|
|
102
|
+
/**
|
|
103
|
+
* Zod fragment for the compact stream truncation metadata fields.
|
|
104
|
+
*
|
|
105
|
+
* Spread into a tool's result schema so `structuredContent` produced with
|
|
106
|
+
* {@link compactStreamFields} validates:
|
|
107
|
+
* ```ts
|
|
108
|
+
* const MyResultSchema = z.object({
|
|
109
|
+
* exitCode: z.number(),
|
|
110
|
+
* stdout: z.string().optional(),
|
|
111
|
+
* stderr: z.string().optional(),
|
|
112
|
+
* ...CompactStreamSchemaFields,
|
|
113
|
+
* });
|
|
114
|
+
* ```
|
|
115
|
+
*
|
|
116
|
+
* Field-compatible with the `server-process` run schema from PR #1020.
|
|
117
|
+
*/
|
|
118
|
+
export declare const CompactStreamSchemaFields: {
|
|
119
|
+
/** Whether stdout was truncated to the compact output budget (only set when true). */
|
|
120
|
+
stdoutTruncated: z.ZodOptional<z.ZodBoolean>;
|
|
121
|
+
/** Whether stderr was truncated to the compact output budget (only set when true). */
|
|
122
|
+
stderrTruncated: z.ZodOptional<z.ZodBoolean>;
|
|
123
|
+
/** Total stdout lines before compact truncation (only set when stdoutTruncated). */
|
|
124
|
+
stdoutTotalLines: z.ZodOptional<z.ZodNumber>;
|
|
125
|
+
/** Total stderr lines before compact truncation (only set when stderrTruncated). */
|
|
126
|
+
stderrTotalLines: z.ZodOptional<z.ZodNumber>;
|
|
127
|
+
};
|
|
128
|
+
//# sourceMappingURL=compact.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compact.d.ts","sourceRoot":"","sources":["../src/compact.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;GAGG;AACH,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC;;;GAGG;AACH,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC;;;GAGG;AACH,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAErC,0EAA0E;AAC1E,MAAM,WAAW,qBAAqB;IACpC,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wCAAwC;AACxC,MAAM,WAAW,oBAAoB;IACnC,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,SAAS,EAAE,OAAO,CAAC;IACnB,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,qBAA0B,GAC/B,oBAAoB,CA0BtB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,IAAI,CAAC;IACvB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,IAAI,CAAC;IACvB,+EAA+E;IAC/E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,+EAA+E;IAC/E,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,IAAI,GAAE,qBAA0B,GAC/B,mBAAmB,CAqBrB;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,yBAAyB;IACpC,sFAAsF;;IAEtF,sFAAsF;;IAEtF,oFAAoF;;IAEpF,oFAAoF;;CAErF,CAAC"}
|
package/dist/compact.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Default number of leading lines kept when truncating a stream for compact
|
|
4
|
+
* output. Matches the budget introduced for `server-process` in PR #1020.
|
|
5
|
+
*/
|
|
6
|
+
export const COMPACT_HEAD_LINES = 40;
|
|
7
|
+
/**
|
|
8
|
+
* Default number of trailing lines kept when truncating a stream for compact
|
|
9
|
+
* output. Matches the budget introduced for `server-process` in PR #1020.
|
|
10
|
+
*/
|
|
11
|
+
export const COMPACT_TAIL_LINES = 10;
|
|
12
|
+
/**
|
|
13
|
+
* Default hard byte cap applied to each stream after line trimming.
|
|
14
|
+
* Matches the budget introduced for `server-process` in PR #1020.
|
|
15
|
+
*/
|
|
16
|
+
export const COMPACT_BYTE_CAP = 8192;
|
|
17
|
+
/**
|
|
18
|
+
* Truncates a stream (stdout/stderr) to a compact budget: the first
|
|
19
|
+
* `headLines` lines and the last `tailLines` lines with a
|
|
20
|
+
* `... (N lines omitted) ...` marker in between, followed by a hard byte cap
|
|
21
|
+
* that appends `... (truncated)` when exceeded.
|
|
22
|
+
*
|
|
23
|
+
* Behaviorally identical to the compact truncation shipped for
|
|
24
|
+
* `server-process` in PR #1020, extracted so every server can share it
|
|
25
|
+
* (epic #1022).
|
|
26
|
+
*
|
|
27
|
+
* Notes:
|
|
28
|
+
* - Lines are split on `"\n"`; CRLF input keeps its `"\r"` characters and a
|
|
29
|
+
* trailing newline counts as one extra (empty) line, mirroring the
|
|
30
|
+
* reference implementation.
|
|
31
|
+
* - The byte cap is applied to the JavaScript string length (UTF-16 code
|
|
32
|
+
* units), matching the original implementation.
|
|
33
|
+
*
|
|
34
|
+
* @param text - The raw stream text to truncate.
|
|
35
|
+
* @param opts - Optional budget overrides (see {@link TruncateStreamOptions}).
|
|
36
|
+
* @returns The truncated text, whether truncation occurred, and the total
|
|
37
|
+
* line count of the original text.
|
|
38
|
+
*/
|
|
39
|
+
export function truncateStream(text, opts = {}) {
|
|
40
|
+
const headLines = opts.headLines ?? COMPACT_HEAD_LINES;
|
|
41
|
+
const tailLines = opts.tailLines ?? COMPACT_TAIL_LINES;
|
|
42
|
+
const byteCap = opts.byteCap ?? COMPACT_BYTE_CAP;
|
|
43
|
+
const lines = text.split("\n");
|
|
44
|
+
const totalLines = lines.length;
|
|
45
|
+
let out = text;
|
|
46
|
+
let truncated = false;
|
|
47
|
+
if (totalLines > headLines + tailLines) {
|
|
48
|
+
const omitted = totalLines - headLines - tailLines;
|
|
49
|
+
out = [
|
|
50
|
+
...lines.slice(0, headLines),
|
|
51
|
+
`... (${omitted} lines omitted) ...`,
|
|
52
|
+
...lines.slice(totalLines - tailLines),
|
|
53
|
+
].join("\n");
|
|
54
|
+
truncated = true;
|
|
55
|
+
}
|
|
56
|
+
if (out.length > byteCap) {
|
|
57
|
+
out = out.slice(0, byteCap) + "\n... (truncated)";
|
|
58
|
+
truncated = true;
|
|
59
|
+
}
|
|
60
|
+
return { text: out, truncated, totalLines };
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Builds the compact stdout/stderr field set used by compact tool results.
|
|
64
|
+
*
|
|
65
|
+
* Convenience wrapper around {@link truncateStream} producing the exact
|
|
66
|
+
* optional-field shape shipped for `server-process` in PR #1020:
|
|
67
|
+
*
|
|
68
|
+
* - Empty or `undefined` streams are omitted entirely (no `stdout: ""`).
|
|
69
|
+
* - `stdoutTruncated`/`stderrTruncated` are set (to `true`) only when the
|
|
70
|
+
* corresponding stream was actually truncated — never `false`.
|
|
71
|
+
* - `stdoutTotalLines`/`stderrTotalLines` are set only when the
|
|
72
|
+
* corresponding truncated flag is set.
|
|
73
|
+
*
|
|
74
|
+
* Spread the result into a compact result object:
|
|
75
|
+
* ```ts
|
|
76
|
+
* const compact = { exitCode, success, ...compactStreamFields(stdout, stderr) };
|
|
77
|
+
* ```
|
|
78
|
+
*
|
|
79
|
+
* @param stdout - Raw stdout text (empty/undefined streams are omitted).
|
|
80
|
+
* @param stderr - Raw stderr text (empty/undefined streams are omitted).
|
|
81
|
+
* @param opts - Optional budget overrides (see {@link TruncateStreamOptions}).
|
|
82
|
+
* @returns An object containing only the fields that apply.
|
|
83
|
+
*/
|
|
84
|
+
export function compactStreamFields(stdout, stderr, opts = {}) {
|
|
85
|
+
const fields = {};
|
|
86
|
+
if (stdout) {
|
|
87
|
+
const t = truncateStream(stdout, opts);
|
|
88
|
+
fields.stdout = t.text;
|
|
89
|
+
if (t.truncated) {
|
|
90
|
+
fields.stdoutTruncated = true;
|
|
91
|
+
fields.stdoutTotalLines = t.totalLines;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (stderr) {
|
|
95
|
+
const t = truncateStream(stderr, opts);
|
|
96
|
+
fields.stderr = t.text;
|
|
97
|
+
if (t.truncated) {
|
|
98
|
+
fields.stderrTruncated = true;
|
|
99
|
+
fields.stderrTotalLines = t.totalLines;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return fields;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Zod fragment for the compact stream truncation metadata fields.
|
|
106
|
+
*
|
|
107
|
+
* Spread into a tool's result schema so `structuredContent` produced with
|
|
108
|
+
* {@link compactStreamFields} validates:
|
|
109
|
+
* ```ts
|
|
110
|
+
* const MyResultSchema = z.object({
|
|
111
|
+
* exitCode: z.number(),
|
|
112
|
+
* stdout: z.string().optional(),
|
|
113
|
+
* stderr: z.string().optional(),
|
|
114
|
+
* ...CompactStreamSchemaFields,
|
|
115
|
+
* });
|
|
116
|
+
* ```
|
|
117
|
+
*
|
|
118
|
+
* Field-compatible with the `server-process` run schema from PR #1020.
|
|
119
|
+
*/
|
|
120
|
+
export const CompactStreamSchemaFields = {
|
|
121
|
+
/** Whether stdout was truncated to the compact output budget (only set when true). */
|
|
122
|
+
stdoutTruncated: z.boolean().optional(),
|
|
123
|
+
/** Whether stderr was truncated to the compact output budget (only set when true). */
|
|
124
|
+
stderrTruncated: z.boolean().optional(),
|
|
125
|
+
/** Total stdout lines before compact truncation (only set when stdoutTruncated). */
|
|
126
|
+
stdoutTotalLines: z.number().optional(),
|
|
127
|
+
/** Total stderr lines before compact truncation (only set when stderrTruncated). */
|
|
128
|
+
stderrTotalLines: z.number().optional(),
|
|
129
|
+
};
|
|
130
|
+
//# sourceMappingURL=compact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compact.js","sourceRoot":"","sources":["../src/compact.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** Options for {@link surfaceEmptyFailure}. */
|
|
3
|
+
export interface SurfaceEmptyFailureOptions<T extends object> {
|
|
4
|
+
/**
|
|
5
|
+
* Predicate deciding whether the parsed data is "empty" — i.e. the parser
|
|
6
|
+
* found nothing actionable (zero tests, zero diagnostics, zero results).
|
|
7
|
+
*/
|
|
8
|
+
isEmpty: (data: T) => boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Maximum number of characters of raw output to attach as the `error`
|
|
11
|
+
* detail (the tail of the stream is kept). Default 4096.
|
|
12
|
+
*/
|
|
13
|
+
maxBytes?: number;
|
|
14
|
+
}
|
|
15
|
+
/** Default maximum error detail length for {@link surfaceEmptyFailure}. */
|
|
16
|
+
export declare const SURFACE_EMPTY_FAILURE_MAX_BYTES = 4096;
|
|
17
|
+
/**
|
|
18
|
+
* Surfaces a "silent green" failure: the CLI exited non-zero but the parser
|
|
19
|
+
* produced no results, which would otherwise read as a clean/passing run.
|
|
20
|
+
*
|
|
21
|
+
* When `result.exitCode !== 0`, `opts.isEmpty(data)` is true, and no `error`
|
|
22
|
+
* field is already set on `data`, this returns a copy of `data` with:
|
|
23
|
+
*
|
|
24
|
+
* - `error` — the trimmed tail (last `maxBytes` characters) of whichever
|
|
25
|
+
* stream has content, preferring stderr when non-empty, else stdout. When
|
|
26
|
+
* the detail exceeds `maxBytes` a `… (output truncated)` marker is
|
|
27
|
+
* prepended to the kept tail. When both streams are empty a fallback
|
|
28
|
+
* message is used so the `error` field is never an empty string.
|
|
29
|
+
* - `exitCode` — the CLI's exit code.
|
|
30
|
+
*
|
|
31
|
+
* Otherwise `data` is returned unchanged (same reference).
|
|
32
|
+
*
|
|
33
|
+
* Generalizes `server-test`'s `surfaceLoadFailure` (issues #928/#931) for
|
|
34
|
+
* every server (epic #1024): a test suite that fails at import/collection
|
|
35
|
+
* time, a linter that crashes before emitting JSON, etc., all exit non-zero
|
|
36
|
+
* with nothing parseable — this makes that state visible to agents.
|
|
37
|
+
*
|
|
38
|
+
* Layering note: this is NOT a replacement for `classifyError`/`errorOutput`
|
|
39
|
+
* (see `errors.ts`). Those handle "the command itself failed and the tool
|
|
40
|
+
* returns an error response". `surfaceEmptyFailure` covers the layer above:
|
|
41
|
+
* the CLI ran, the tool still returns a structured (non-error) result, but
|
|
42
|
+
* the output contained nothing parseable — so the result must carry evidence
|
|
43
|
+
* of the failure instead of looking like a clean pass.
|
|
44
|
+
*
|
|
45
|
+
* @param data - The parsed result object (returned as-is when no failure is surfaced).
|
|
46
|
+
* @param result - The raw CLI outcome (exit code plus captured streams).
|
|
47
|
+
* @param opts - Emptiness predicate and optional detail size cap.
|
|
48
|
+
* @returns `data`, possibly augmented with `error` and `exitCode`.
|
|
49
|
+
*/
|
|
50
|
+
export declare function surfaceEmptyFailure<T extends object>(data: T, result: {
|
|
51
|
+
exitCode: number;
|
|
52
|
+
stdout: string;
|
|
53
|
+
stderr: string;
|
|
54
|
+
}, opts: SurfaceEmptyFailureOptions<T>): T & {
|
|
55
|
+
error?: string;
|
|
56
|
+
exitCode?: number;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Zod fragment for the fields {@link surfaceEmptyFailure} may attach.
|
|
60
|
+
*
|
|
61
|
+
* Spread into a tool's result schema so augmented results validate:
|
|
62
|
+
* ```ts
|
|
63
|
+
* const MyResultSchema = z.object({
|
|
64
|
+
* summary: SummarySchema,
|
|
65
|
+
* ...EmptyFailureSchemaFields,
|
|
66
|
+
* });
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export declare const EmptyFailureSchemaFields: {
|
|
70
|
+
/** Raw CLI output surfaced when the run failed but nothing was parseable. */
|
|
71
|
+
error: z.ZodOptional<z.ZodString>;
|
|
72
|
+
/** CLI exit code, set alongside `error` when a silent failure was surfaced. */
|
|
73
|
+
exitCode: z.ZodOptional<z.ZodNumber>;
|
|
74
|
+
};
|
|
75
|
+
//# sourceMappingURL=diagnostics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,+CAA+C;AAC/C,MAAM,WAAW,0BAA0B,CAAC,CAAC,SAAS,MAAM;IAC1D;;;OAGG;IACH,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC;IAC9B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,2EAA2E;AAC3E,eAAO,MAAM,+BAA+B,OAAO,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,MAAM,EAClD,IAAI,EAAE,CAAC,EACP,MAAM,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAC5D,IAAI,EAAE,0BAA0B,CAAC,CAAC,CAAC,GAClC,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAkB3C;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,wBAAwB;IACnC,6EAA6E;;IAE7E,+EAA+E;;CAEhF,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** Default maximum error detail length for {@link surfaceEmptyFailure}. */
|
|
3
|
+
export const SURFACE_EMPTY_FAILURE_MAX_BYTES = 4096;
|
|
4
|
+
/**
|
|
5
|
+
* Surfaces a "silent green" failure: the CLI exited non-zero but the parser
|
|
6
|
+
* produced no results, which would otherwise read as a clean/passing run.
|
|
7
|
+
*
|
|
8
|
+
* When `result.exitCode !== 0`, `opts.isEmpty(data)` is true, and no `error`
|
|
9
|
+
* field is already set on `data`, this returns a copy of `data` with:
|
|
10
|
+
*
|
|
11
|
+
* - `error` — the trimmed tail (last `maxBytes` characters) of whichever
|
|
12
|
+
* stream has content, preferring stderr when non-empty, else stdout. When
|
|
13
|
+
* the detail exceeds `maxBytes` a `… (output truncated)` marker is
|
|
14
|
+
* prepended to the kept tail. When both streams are empty a fallback
|
|
15
|
+
* message is used so the `error` field is never an empty string.
|
|
16
|
+
* - `exitCode` — the CLI's exit code.
|
|
17
|
+
*
|
|
18
|
+
* Otherwise `data` is returned unchanged (same reference).
|
|
19
|
+
*
|
|
20
|
+
* Generalizes `server-test`'s `surfaceLoadFailure` (issues #928/#931) for
|
|
21
|
+
* every server (epic #1024): a test suite that fails at import/collection
|
|
22
|
+
* time, a linter that crashes before emitting JSON, etc., all exit non-zero
|
|
23
|
+
* with nothing parseable — this makes that state visible to agents.
|
|
24
|
+
*
|
|
25
|
+
* Layering note: this is NOT a replacement for `classifyError`/`errorOutput`
|
|
26
|
+
* (see `errors.ts`). Those handle "the command itself failed and the tool
|
|
27
|
+
* returns an error response". `surfaceEmptyFailure` covers the layer above:
|
|
28
|
+
* the CLI ran, the tool still returns a structured (non-error) result, but
|
|
29
|
+
* the output contained nothing parseable — so the result must carry evidence
|
|
30
|
+
* of the failure instead of looking like a clean pass.
|
|
31
|
+
*
|
|
32
|
+
* @param data - The parsed result object (returned as-is when no failure is surfaced).
|
|
33
|
+
* @param result - The raw CLI outcome (exit code plus captured streams).
|
|
34
|
+
* @param opts - Emptiness predicate and optional detail size cap.
|
|
35
|
+
* @returns `data`, possibly augmented with `error` and `exitCode`.
|
|
36
|
+
*/
|
|
37
|
+
export function surfaceEmptyFailure(data, result, opts) {
|
|
38
|
+
if (result.exitCode === 0 || !opts.isEmpty(data)) {
|
|
39
|
+
return data;
|
|
40
|
+
}
|
|
41
|
+
if (data.error) {
|
|
42
|
+
return data;
|
|
43
|
+
}
|
|
44
|
+
const maxBytes = opts.maxBytes ?? SURFACE_EMPTY_FAILURE_MAX_BYTES;
|
|
45
|
+
const detail = (result.stderr.trim() || result.stdout.trim()).trim();
|
|
46
|
+
const error = detail.length > maxBytes
|
|
47
|
+
? `… (output truncated)\n${detail.slice(-maxBytes)}`
|
|
48
|
+
: detail ||
|
|
49
|
+
`Command exited with code ${result.exitCode} but produced no parseable output. ` +
|
|
50
|
+
`This is not a passing run.`;
|
|
51
|
+
return { ...data, error, exitCode: result.exitCode };
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Zod fragment for the fields {@link surfaceEmptyFailure} may attach.
|
|
55
|
+
*
|
|
56
|
+
* Spread into a tool's result schema so augmented results validate:
|
|
57
|
+
* ```ts
|
|
58
|
+
* const MyResultSchema = z.object({
|
|
59
|
+
* summary: SummarySchema,
|
|
60
|
+
* ...EmptyFailureSchemaFields,
|
|
61
|
+
* });
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export const EmptyFailureSchemaFields = {
|
|
65
|
+
/** Raw CLI output surfaced when the run failed but nothing was parseable. */
|
|
66
|
+
error: z.string().optional(),
|
|
67
|
+
/** CLI exit code, set alongside `error` when a silent failure was surfaced. */
|
|
68
|
+
exitCode: z.number().optional(),
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=diagnostics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAgBxB,2EAA2E;AAC3E,MAAM,CAAC,MAAM,+BAA+B,GAAG,IAAI,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAAO,EACP,MAA4D,EAC5D,IAAmC;IAEnC,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACjD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAK,IAA4B,CAAC,KAAK,EAAE,CAAC;QACxC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,+BAA+B,CAAC;IAClE,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACrE,MAAM,KAAK,GACT,MAAM,CAAC,MAAM,GAAG,QAAQ;QACtB,CAAC,CAAC,yBAAyB,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,EAAE;QACpD,CAAC,CAAC,MAAM;YACN,4BAA4B,MAAM,CAAC,QAAQ,qCAAqC;gBAC9E,4BAA4B,CAAC;IAErC,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;AACvD,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,6EAA6E;IAC7E,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,+EAA+E;IAC/E,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAChC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,10 @@ export { coerceJsonArray, assertNoFlagInjection, assertSafePassthroughArg, asser
|
|
|
6
6
|
export { INPUT_LIMITS } from "./limits.js";
|
|
7
7
|
export { compactInput, projectPathInput, repoPathInput, cwdPathInput, fixInput, pathInput, configInput, filePatternsInput, } from "./input-schemas.js";
|
|
8
8
|
export { sanitizeErrorOutput } from "./sanitize.js";
|
|
9
|
+
export { COMPACT_HEAD_LINES, COMPACT_TAIL_LINES, COMPACT_BYTE_CAP, truncateStream, compactStreamFields, CompactStreamSchemaFields, } from "./compact.js";
|
|
10
|
+
export type { TruncateStreamOptions, TruncateStreamResult, CompactStreamFields, } from "./compact.js";
|
|
11
|
+
export { surfaceEmptyFailure, SURFACE_EMPTY_FAILURE_MAX_BYTES, EmptyFailureSchemaFields, } from "./diagnostics.js";
|
|
12
|
+
export type { SurfaceEmptyFailureOptions } from "./diagnostics.js";
|
|
9
13
|
export { shouldRegisterTool, isLazyEnabled, _resetProfileCache } from "./tool-filter.js";
|
|
10
14
|
export { PROFILES, CORE_TOOLS, resolveProfile, isCoreToolForServer } from "./profiles.js";
|
|
11
15
|
export type { ProfileName } from "./profiles.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,GAAG,EACH,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,WAAW,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,2BAA2B,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC1F,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,wBAAwB,EACxB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,WAAW,EACX,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAC1F,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EACL,qBAAqB,EACrB,KAAK,kBAAkB,EACvB,KAAK,eAAe,GACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,4BAA4B,GAC7B,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,cAAc,EACd,WAAW,EACX,UAAU,EACV,UAAU,EACV,eAAe,EACf,oBAAoB,GACrB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,GAAG,EACH,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,WAAW,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,2BAA2B,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC1F,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,wBAAwB,EACxB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,WAAW,EACX,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACnB,yBAAyB,GAC1B,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,mBAAmB,EACnB,+BAA+B,EAC/B,wBAAwB,GACzB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAC1F,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EACL,qBAAqB,EACrB,KAAK,kBAAkB,EACvB,KAAK,eAAe,GACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,4BAA4B,GAC7B,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,cAAc,EACd,WAAW,EACX,UAAU,EACV,UAAU,EACV,eAAe,EACf,oBAAoB,GACrB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,8 @@ export { coerceJsonArray, assertNoFlagInjection, assertSafePassthroughArg, asser
|
|
|
6
6
|
export { INPUT_LIMITS } from "./limits.js";
|
|
7
7
|
export { compactInput, projectPathInput, repoPathInput, cwdPathInput, fixInput, pathInput, configInput, filePatternsInput, } from "./input-schemas.js";
|
|
8
8
|
export { sanitizeErrorOutput } from "./sanitize.js";
|
|
9
|
+
export { COMPACT_HEAD_LINES, COMPACT_TAIL_LINES, COMPACT_BYTE_CAP, truncateStream, compactStreamFields, CompactStreamSchemaFields, } from "./compact.js";
|
|
10
|
+
export { surfaceEmptyFailure, SURFACE_EMPTY_FAILURE_MAX_BYTES, EmptyFailureSchemaFields, } from "./diagnostics.js";
|
|
9
11
|
export { shouldRegisterTool, isLazyEnabled, _resetProfileCache } from "./tool-filter.js";
|
|
10
12
|
export { PROFILES, CORE_TOOLS, resolveProfile, isCoreToolForServer } from "./profiles.js";
|
|
11
13
|
export { createLazyToolManager, } from "./lazy-tools.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,GAAG,EACH,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,GAIhB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,2BAA2B,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC1F,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,wBAAwB,EACxB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,WAAW,EACX,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAE1F,OAAO,EACL,qBAAqB,GAGtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,4BAA4B,GAC7B,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,cAAc,EACd,WAAW,EACX,UAAU,EACV,UAAU,EACV,eAAe,EACf,oBAAoB,GACrB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,GAAG,EACH,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,GAIhB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,2BAA2B,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC1F,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,wBAAwB,EACxB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,WAAW,EACX,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACnB,yBAAyB,GAC1B,MAAM,cAAc,CAAC;AAMtB,OAAO,EACL,mBAAmB,EACnB,+BAA+B,EAC/B,wBAAwB,GACzB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAE1F,OAAO,EACL,qBAAqB,GAGtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,4BAA4B,GAC7B,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,cAAc,EACd,WAAW,EACX,UAAU,EACV,UAAU,EACV,eAAe,EACf,oBAAoB,GACrB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { JsonSchemaType } from "@modelcontextprotocol/sdk/validation/types.js";
|
|
2
|
+
/** Result of validating a tool output payload against its registered schema. */
|
|
3
|
+
export interface ToolOutputValidationResult {
|
|
4
|
+
valid: boolean;
|
|
5
|
+
/** AJV error message when invalid (mirrors the MCP client's -32602 detail). */
|
|
6
|
+
errorMessage?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Converts a Zod outputSchema to JSON Schema exactly like the MCP SDK does
|
|
10
|
+
* when listing tools (zod v4 branch of `toJsonSchemaCompat`): draft-7 target,
|
|
11
|
+
* output io — which makes plain `z.object` emit `additionalProperties: false`.
|
|
12
|
+
*/
|
|
13
|
+
export declare function toolOutputJsonSchema(outputSchema: unknown): JsonSchemaType;
|
|
14
|
+
/**
|
|
15
|
+
* Validates a structuredContent payload against a tool's registered Zod
|
|
16
|
+
* outputSchema using the SDK's own AJV validator. The payload is JSON
|
|
17
|
+
* round-tripped first to mirror the wire (drops `undefined`-valued keys).
|
|
18
|
+
*/
|
|
19
|
+
export declare function validateToolOutput(outputSchema: unknown, structuredContent: unknown): ToolOutputValidationResult;
|
|
20
|
+
/**
|
|
21
|
+
* Assertion form of {@link validateToolOutput}: throws with the AJV error
|
|
22
|
+
* detail when the payload would be rejected by an MCP client at runtime.
|
|
23
|
+
*/
|
|
24
|
+
export declare function expectToolOutputMatchesSchema(outputSchema: unknown, structuredContent: unknown): void;
|
|
25
|
+
//# sourceMappingURL=testing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+CAA+C,CAAC;AAEpF,gFAAgF;AAChF,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,OAAO,CAAC;IACf,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,OAAO,GAAG,cAAc,CAK1E;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,OAAO,EACrB,iBAAiB,EAAE,OAAO,GACzB,0BAA0B,CAM5B;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAC3C,YAAY,EAAE,OAAO,EACrB,iBAAiB,EAAE,OAAO,GACzB,IAAI,CAQN"}
|
package/dist/testing.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test-only helpers that validate tool output the exact way the MCP SDK does
|
|
3
|
+
* at runtime.
|
|
4
|
+
*
|
|
5
|
+
* Why this exists (#1022 regression class): Zod's `.parse()` silently STRIPS
|
|
6
|
+
* unknown keys, so `Schema.parse(compactMap(data))` passes even when a compact
|
|
7
|
+
* mapper emits fields the registered `outputSchema` does not declare. The MCP
|
|
8
|
+
* SDK, however, converts the Zod outputSchema to JSON Schema (where plain
|
|
9
|
+
* `z.object` becomes `additionalProperties: false`) and validates
|
|
10
|
+
* `structuredContent` with AJV on the client side — so undeclared compact-only
|
|
11
|
+
* fields fail at runtime with `MCP error -32602: data must NOT have
|
|
12
|
+
* additional properties`, but only when compact mode engages.
|
|
13
|
+
*
|
|
14
|
+
* These helpers replicate that pipeline (zod v4 `toJSONSchema` with the SDK's
|
|
15
|
+
* options + the SDK's own AJV validator) so unit tests catch the mismatch.
|
|
16
|
+
*
|
|
17
|
+
* Import from `@paretools/shared/testing` — kept out of the main entry point
|
|
18
|
+
* so production servers never load AJV.
|
|
19
|
+
*/
|
|
20
|
+
import * as z4mini from "zod/v4-mini";
|
|
21
|
+
import { AjvJsonSchemaValidator } from "@modelcontextprotocol/sdk/validation/ajv";
|
|
22
|
+
/**
|
|
23
|
+
* Converts a Zod outputSchema to JSON Schema exactly like the MCP SDK does
|
|
24
|
+
* when listing tools (zod v4 branch of `toJsonSchemaCompat`): draft-7 target,
|
|
25
|
+
* output io — which makes plain `z.object` emit `additionalProperties: false`.
|
|
26
|
+
*/
|
|
27
|
+
export function toolOutputJsonSchema(outputSchema) {
|
|
28
|
+
return z4mini.toJSONSchema(outputSchema, {
|
|
29
|
+
target: "draft-7",
|
|
30
|
+
io: "output",
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Validates a structuredContent payload against a tool's registered Zod
|
|
35
|
+
* outputSchema using the SDK's own AJV validator. The payload is JSON
|
|
36
|
+
* round-tripped first to mirror the wire (drops `undefined`-valued keys).
|
|
37
|
+
*/
|
|
38
|
+
export function validateToolOutput(outputSchema, structuredContent) {
|
|
39
|
+
const jsonSchema = toolOutputJsonSchema(outputSchema);
|
|
40
|
+
const validate = new AjvJsonSchemaValidator().getValidator(jsonSchema);
|
|
41
|
+
const wireData = JSON.parse(JSON.stringify(structuredContent));
|
|
42
|
+
const result = validate(wireData);
|
|
43
|
+
return result.valid ? { valid: true } : { valid: false, errorMessage: result.errorMessage };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Assertion form of {@link validateToolOutput}: throws with the AJV error
|
|
47
|
+
* detail when the payload would be rejected by an MCP client at runtime.
|
|
48
|
+
*/
|
|
49
|
+
export function expectToolOutputMatchesSchema(outputSchema, structuredContent) {
|
|
50
|
+
const result = validateToolOutput(outputSchema, structuredContent);
|
|
51
|
+
if (!result.valid) {
|
|
52
|
+
throw new Error(`structuredContent does not validate against the registered outputSchema ` +
|
|
53
|
+
`(the MCP client would reject this with -32602): ${result.errorMessage}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=testing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,sBAAsB,EAAE,MAAM,0CAA0C,CAAC;AAUlF;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,YAAqB;IACxD,OAAO,MAAM,CAAC,YAAY,CAAC,YAAyD,EAAE;QACpF,MAAM,EAAE,SAAS;QACjB,EAAE,EAAE,QAAQ;KACb,CAAmB,CAAC;AACvB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,YAAqB,EACrB,iBAA0B;IAE1B,MAAM,UAAU,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,IAAI,sBAAsB,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;IACvE,MAAM,QAAQ,GAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACxE,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAClC,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC;AAC9F,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,6BAA6B,CAC3C,YAAqB,EACrB,iBAA0B;IAE1B,MAAM,MAAM,GAAG,kBAAkB,CAAC,YAAY,EAAE,iBAAiB,CAAC,CAAC;IACnE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CACb,0EAA0E;YACxE,mDAAmD,MAAM,CAAC,YAAY,EAAE,CAC3E,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paretools/shared",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "Shared utilities for Pare MCP servers",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -23,6 +23,10 @@
|
|
|
23
23
|
".": {
|
|
24
24
|
"types": "./dist/index.d.ts",
|
|
25
25
|
"default": "./dist/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./testing": {
|
|
28
|
+
"types": "./dist/testing.d.ts",
|
|
29
|
+
"default": "./dist/testing.js"
|
|
26
30
|
}
|
|
27
31
|
},
|
|
28
32
|
"publishConfig": {
|
|
@@ -40,11 +44,11 @@
|
|
|
40
44
|
"dist"
|
|
41
45
|
],
|
|
42
46
|
"dependencies": {
|
|
43
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
47
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
44
48
|
"zod": "^4.4.3"
|
|
45
49
|
},
|
|
46
50
|
"devDependencies": {
|
|
47
|
-
"@types/node": "^26.1.
|
|
51
|
+
"@types/node": "^26.1.2",
|
|
48
52
|
"typescript": "^6.0.3",
|
|
49
53
|
"vitest": "^4.1.10",
|
|
50
54
|
"@paretools/tsconfig": "0.0.0"
|