@agimon-ai/foundation-validator 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,52 @@
1
+ Business Source License 1.1
2
+
3
+ Parameters
4
+
5
+ Licensor: AgiFlow
6
+ Licensed Work: @agimon-ai/public-packages
7
+ The Licensed Work is (c) 2026 AgiFlow.
8
+ Additional Use Grant: None
9
+ Change Date: 2030-03-06
10
+ Change License: Apache License, Version 2.0
11
+
12
+ Terms
13
+
14
+ The Licensor hereby grants you the right to copy, modify, create derivative
15
+ works, redistribute, and make non-production use of the Licensed Work. The
16
+ Licensor may make an Additional Use Grant, above, permitting limited
17
+ production use.
18
+
19
+ Effective on the Change Date, or the fourth anniversary of the first publicly
20
+ available distribution of a specific version of the Licensed Work under this
21
+ License, whichever comes first, the Licensor hereby grants you rights under
22
+ the terms of the Change License, and the rights granted in the paragraph
23
+ above terminate.
24
+
25
+ If your use of the Licensed Work does not comply with the requirements
26
+ currently in effect as described in this License, you must purchase a
27
+ commercial license from the Licensor, its affiliated entities, or authorized
28
+ resellers, or you must refrain from using the Licensed Work.
29
+
30
+ All copies of the original and modified Licensed Work, and derivative works
31
+ of the Licensed Work, are subject to this License. This License applies
32
+ separately for each version of the Licensed Work and the Change Date may vary
33
+ for each version of the Licensed Work released by Licensor.
34
+
35
+ You must conspicuously display this License on each original or modified copy
36
+ of the Licensed Work. If you receive the Licensed Work in original or
37
+ modified form from a third party, the terms and conditions set forth in this
38
+ License apply to your use of that work.
39
+
40
+ Any use of the Licensed Work in violation of this License will automatically
41
+ terminate your rights under this License for the current and all other
42
+ versions of the Licensed Work.
43
+
44
+ This License does not grant you any right in any trademark or logo of
45
+ Licensor or its affiliates (provided that you may use a trademark or logo of
46
+ Licensor as expressly required by this License).
47
+
48
+ TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
49
+ AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
50
+ EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
51
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
52
+ TITLE.
package/dist/index.cjs ADDED
@@ -0,0 +1,4 @@
1
+ let e=require(`zod`);function t(e){return e._def.type??``}function n(e){let r=t(e);if(r===`optional`||r===`nullable`||r===`default`){let t=e._def.innerType;return t?n(t):e}return e}function r(e){let i=n(e),a=t(i);return a===`object`||a===`array`||a===`record`?!0:a===`union`?(i._def.options??[]).some(r):!1}function i(e,t){let n={...e};for(let[e,i]of Object.entries(t.shape)){let t=n[e];if(typeof t==`string`&&r(i))try{n[e]=JSON.parse(t)}catch{}}return n}function a(e){return e._def.type??``}function o(e){return e._def.innerType}function s(e){let t=a(e);return t!==`optional`&&t!==`default`}function c(e){switch(a(e)){case`string`:return`string`;case`number`:return`number`;case`boolean`:return`boolean`;case`bigint`:return`bigint`;case`null`:return`null`;case`undefined`:return`undefined`;case`any`:return`any`;case`unknown`:return`unknown`;case`literal`:return JSON.stringify(e._def.value);case`enum`:return`enum [${(e.options??[]).join(`, `)}]`;case`array`:{let t=e._def.element;return t?`${c(t)}[]`:`unknown[]`}case`record`:{let t=e._def.valueType;return t?`Record<string, ${c(t)}>`:`Record<string, unknown>`}case`object`:return`object`;case`optional`:case`nullable`:case`default`:{let t=o(e);return t?c(t):`unknown`}case`union`:return(e._def.options??[]).map(c).join(` | `);default:return`unknown`}}function l(e){return e.match(/received (\w+)(?:\s|$)/)?.[1]}function u(e){switch(e.code){case`invalid_type`:{let t=e;return l(t.message)===`undefined`?`Required field is missing`:t.message}case`invalid_value`:return`Invalid value — must be one of: ${e.values.join(`, `)}`;case`too_small`:{let t=e;return`Value too small — minimum is ${String(t.minimum)}${t.inclusive?` (inclusive)`:` (exclusive)`}`}case`too_big`:{let t=e;return`Value too large — maximum is ${String(t.maximum)}${t.inclusive?` (inclusive)`:` (exclusive)`}`}case`unrecognized_keys`:return`Unrecognized keys: ${e.keys.join(`, `)}`;default:return e.message}}function d(e,t,n){let r=`--${t}`;switch(e.code){case`invalid_type`:{let t=e,i=l(t.message);return i===`undefined`?`Provide: ${r} <${n?c(n):`value`}>`:i===`string`&&(t.expected===`record`||t.expected===`array`||t.expected===`object`)?`Received a JSON string instead of ${t.expected}.\n → The coercion layer should handle this automatically.\n → CLI usage: ${r} '<json ${t.expected}>'`:void 0}case`invalid_value`:{let t=e.values[0];return`Use: ${r} ${String(t)}`}default:return}}function f(e,t){if(e.length!==0)return t.shape[e[0]]}function p(e,t){let{schemaName:n,schema:r}=t??{},i=new Map;for(let t of e.issues){let e=t.path.length>0?t.path.map(String).join(`.`):`(root)`,n=i.get(e)??[];n.push(t),i.set(e,n)}let a=[n?`Validation failed for "${n}":`:`Validation failed:`];for(let[e,t]of i){a.push(``);let n=r?f(e.split(`.`),r):void 0,i=n?s(n):t.some(e=>{if(e.code!==`invalid_type`)return!1;let t=e.message;return l(t)===`undefined`}),o=n?c(n):``,p=`(${i?`required`:`optional`})${o?` — ${o}`:``}`;a.push(` • ${e} ${p}`);for(let r of t){a.push(` ✗ ${u(r)}`);let t=d(r,e,n);t&&a.push(` → ${t}`)}}return a.join(`
2
+ `)}function m(e){return e._def.type??``}function h(e){return e._def.innerType}function g(e){let t=m(e);if(t===`optional`||t===`nullable`||t===`default`){let t=h(e);return t?g(t):e}return e}function _(e){let t=m(e);return t!==`optional`&&t!==`default`}function v(e){if(m(e)===`default`)return e._def.defaultValue}function y(e){return e.description??``}function b(e){let t=g(e);switch(m(t)){case`boolean`:return`boolean`;case`number`:return`number`;case`object`:case`record`:case`array`:return`json`;case`union`:return(t._def.options??[]).some(e=>{let t=m(g(e));return t===`object`||t===`array`||t===`record`})?`json`:`string`;default:return`string`}}function x(e){let t=g(e);if(m(t)===`enum`)return t.options}function S(e,t){if(t&&t.length>0)return`<${t.join(`|`)}>`;switch(e){case`boolean`:return``;case`number`:return`<number>`;case`json`:return`<json>`;default:return`<string>`}}function C(e,t){let n=b(t),r=x(t),i=v(t),a=y(t);return{flag:`--${e}`,type:n,required:_(t),description:a,default:i,choices:r,typeLabel:c(t)}}const w=36;function T(e,t){return e.length>=t?`${e} `:e.padEnd(t)}function E(e){let t=S(e.type,e.choices),n=t?`${e.flag} ${t}`:e.flag,r=e.type===`json`?` — ${e.typeLabel}`:``,i=e.default===void 0?``:` [default: ${JSON.stringify(e.default)}]`,a=`${e.description}${r}${i}`.trim();return` ${T(n,36)}${a}`}function D(e,t){let n=[],r=t.command??`<tool>`;n.push(`Usage: ${r} [options]`),t.description&&(n.push(``),n.push(t.description));let i=e.filter(e=>e.required),a=e.filter(e=>!e.required);if(i.length>0){n.push(``),n.push(`Required:`);for(let e of i)n.push(E(e))}if(a.length>0){n.push(``),n.push(`Optional:`);for(let e of a)n.push(E(e))}return n.join(`
3
+ `)}function O(e,t){let n=Object.entries(e.shape).map(([e,t])=>C(e,t));return{args:n,help:D(n,t??{})}}function k(e){return(e.startsWith(`--`)?e.slice(2):e).replace(/-([a-z])/gi,(e,t)=>t.toUpperCase())}function A(e,t){let{args:n}=O(t),r=new Map(n.map(e=>[k(e.flag),e])),i=new Map(n.map(e=>[e.flag,e])),a={},o=0;for(;o<e.length;){let t=e[o];if(!t.startsWith(`--`)){o++;continue}if(t.startsWith(`--no-`)){let e=k(t.slice(5));a[e]=!1,o++;continue}let n=t.indexOf(`=`),s,c;n===-1?(s=t,c=void 0):(s=t.slice(0,n),c=t.slice(n+1));let l=k(s),u=r.get(l)??i.get(s);if(u?.type===`boolean`){a[l]=!0,o++;continue}let d;if(c!==void 0)d=c,o++;else if(o+1<e.length&&!e[o+1].startsWith(`--`))d=e[o+1],o+=2;else{a[l]=!0,o++;continue}if(u?.type===`json`)try{a[l]=JSON.parse(d)}catch{a[l]=d}else if(u?.type===`number`){let e=Number.parseFloat(d);a[l]=Number.isNaN(e)?d:e}else a[l]=d}return a}function j(t){if(!t||typeof t!=`object`||Array.isArray(t))return e.z.unknown();let n=t,r=n.anyOf??n.oneOf;if(Array.isArray(r)&&r.length>0){let t=r.map(j);return t.length===1?t[0]:e.z.union([t[0],t[1],...t.slice(2)])}if(Array.isArray(n.enum)&&n.enum.every(e=>typeof e==`string`)){let[t,r,...i]=n.enum;return t===void 0?e.z.unknown():r===void 0?e.z.literal(t):e.z.enum([t,r,...i])}let i=n.type;if(Array.isArray(i)){let t=i.filter(e=>e!==`null`),r=i.includes(`null`);if(t.length===0)return r?e.z.null():e.z.unknown();let a=t.length===1?j({...n,type:t[0]}):e.z.union(t.map(e=>j({...n,type:e})));return r?e.z.union([a,e.z.null()]):a}if(i===`string`)return e.z.string();if(i===`number`||i===`integer`)return e.z.number();if(i===`boolean`)return e.z.boolean();if(i===`null`)return e.z.null();if(i===`array`){let t=n.items?j(n.items):e.z.unknown();return e.z.array(t)}return i===`object`?n.properties&&typeof n.properties==`object`&&!Array.isArray(n.properties)?M(n):e.z.record(e.z.string(),e.z.unknown()):e.z.unknown()}function M(t){let n=t.properties,r=new Set(Array.isArray(t.required)?t.required:[]);if(!n)return e.z.object({});let i={};for(let[e,t]of Object.entries(n)){let n=j(t);i[e]=r.has(e)?n:n.optional()}return e.z.object(i)}exports.cliArgsToObject=A,exports.coerceArgs=i,exports.describeType=c,exports.formatZodError=p,exports.jsonSchemaToZod=M,exports.zodToCliArgs=O;
4
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["defType","defType","defInnerType","isRequired","lines: string[]","lines: string[]","result: Record<string, unknown>","key","flagToken: string","inlineValue: string | undefined","rawValue: string | undefined","z","shape: Record<string, z.ZodTypeAny>"],"sources":["../src/utils/coerceArgs.ts","../src/utils/formatZodError.ts","../src/utils/zodToCliArgs.ts","../src/utils/cliArgsToObject.ts","../src/utils/jsonSchemaToZod.ts"],"sourcesContent":["import { z } from 'zod';\n\n// ---------------------------------------------------------------------------\n// Internal helpers — Zod v4 compatible\n// ---------------------------------------------------------------------------\n\n// Zod v4 schema shapes expose $ZodType internally; use a structural interface\n// to avoid the public ZodType vs $ZodType mismatch.\ninterface ZodLike {\n _def: { type?: string; innerType?: ZodLike; options?: ZodLike[] };\n}\n\nfunction defType(schema: ZodLike): string {\n return schema._def.type ?? '';\n}\n\nfunction unwrapZodLike(schema: ZodLike): ZodLike {\n const t = defType(schema);\n if (t === 'optional' || t === 'nullable' || t === 'default') {\n const inner = schema._def.innerType;\n return inner ? unwrapZodLike(inner) : schema;\n }\n return schema;\n}\n\nfunction isNonPrimitive(schema: ZodLike): boolean {\n const core = unwrapZodLike(schema);\n const t = defType(core);\n if (t === 'object' || t === 'array' || t === 'record') return true;\n if (t === 'union') {\n return (core._def.options ?? []).some(isNonPrimitive);\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Walks a ZodObject's shape and, for any field that expects a non-primitive\n * type (object, array, record, or union containing one), attempts to\n * JSON.parse string values. Leaves the value unchanged if:\n * - it is not a string\n * - the schema expects a primitive\n * - the string is not valid JSON\n *\n * This handles the common Claude Code behaviour of stringifying nested args\n * (e.g. env: '{\"KEY\":\"val\"}' instead of env: { KEY: 'val' }).\n */\nexport function coerceArgs(args: Record<string, unknown>, schema: z.ZodObject<z.ZodRawShape>): Record<string, unknown> {\n const result = { ...args };\n\n for (const [key, rawSchema] of Object.entries(schema.shape)) {\n const value = result[key];\n if (typeof value !== 'string') continue;\n if (!isNonPrimitive(rawSchema as unknown as ZodLike)) continue;\n\n try {\n result[key] = JSON.parse(value);\n } catch {\n // keep as string — not valid JSON\n }\n }\n\n return result;\n}\n","import { z } from 'zod';\n\n// ---------------------------------------------------------------------------\n// Internal schema introspection — Zod v4 compatible\n// ---------------------------------------------------------------------------\n\n// Structural interface compatible with both $ZodType (internal) and ZodType (public)\ninterface ZodLike {\n _def: {\n type?: string;\n innerType?: ZodLike;\n element?: ZodLike;\n valueType?: ZodLike;\n options?: readonly ZodLike[];\n value?: unknown;\n };\n description?: string;\n}\n\nfunction defType(schema: ZodLike): string {\n return schema._def.type ?? '';\n}\n\nfunction defInnerType(schema: ZodLike): ZodLike | undefined {\n return schema._def.innerType;\n}\n\nfunction isRequired(schema: ZodLike): boolean {\n const t = defType(schema);\n return t !== 'optional' && t !== 'default';\n}\n\n/**\n * Produces a concise human-readable type label for a Zod schema.\n * Examples: 'string', 'string[]', 'Record<string, string>', 'enum [a, b]'\n */\nexport function describeType(schema: ZodLike): string {\n const t = defType(schema);\n switch (t) {\n case 'string':\n return 'string';\n case 'number':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'bigint':\n return 'bigint';\n case 'null':\n return 'null';\n case 'undefined':\n return 'undefined';\n case 'any':\n return 'any';\n case 'unknown':\n return 'unknown';\n case 'literal':\n return JSON.stringify(schema._def.value);\n case 'enum': {\n // ZodEnum in v4 exposes .options as a getter\n const opts = (schema as unknown as { options: string[] }).options ?? [];\n return `enum [${opts.join(', ')}]`;\n }\n case 'array': {\n const el = schema._def.element;\n return el ? `${describeType(el)}[]` : 'unknown[]';\n }\n case 'record': {\n const valType = schema._def.valueType;\n return valType ? `Record<string, ${describeType(valType)}>` : 'Record<string, unknown>';\n }\n case 'object':\n return 'object';\n case 'optional':\n case 'nullable':\n case 'default': {\n const inner = defInnerType(schema);\n return inner ? describeType(inner) : 'unknown';\n }\n case 'union': {\n const opts = schema._def.options ?? [];\n return opts.map(describeType).join(' | ');\n }\n default:\n return 'unknown';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Issue formatting — Zod v4 issue shapes\n// ---------------------------------------------------------------------------\n\n// Zod v4 uses 'invalid_value' (not 'invalid_enum_value') for enum violations.\n// Use string cast on issue.code to avoid ZodIssueCode constraint errors.\n\ninterface InvalidTypeIssueV4 {\n code: string;\n expected: string;\n message: string;\n path: (string | number)[];\n}\n\ninterface InvalidValueIssueV4 {\n code: string;\n values: (string | number)[];\n message: string;\n path: (string | number)[];\n}\n\ninterface TooSmallIssueV4 {\n code: string;\n minimum: number | bigint;\n inclusive: boolean;\n message: string;\n path: (string | number)[];\n}\n\ninterface TooBigIssueV4 {\n code: string;\n maximum: number | bigint;\n inclusive: boolean;\n message: string;\n path: (string | number)[];\n}\n\ninterface UnrecognizedKeysIssueV4 {\n code: string;\n keys: string[];\n message: string;\n path: (string | number)[];\n}\n\nfunction extractReceived(message: string): string | undefined {\n return message.match(/received (\\w+)(?:\\s|$)/)?.[1];\n}\n\nfunction formatIssueMessage(issue: z.ZodIssue): string {\n const code = issue.code as string;\n switch (code) {\n case 'invalid_type': {\n const i = issue as unknown as InvalidTypeIssueV4;\n const received = extractReceived(i.message);\n if (received === 'undefined') return 'Required field is missing';\n return i.message;\n }\n // Zod v4 uses 'invalid_value' for enum violations\n case 'invalid_value': {\n const i = issue as unknown as InvalidValueIssueV4;\n return `Invalid value — must be one of: ${i.values.join(', ')}`;\n }\n case 'too_small': {\n const i = issue as unknown as TooSmallIssueV4;\n return `Value too small — minimum is ${String(i.minimum)}${i.inclusive ? ' (inclusive)' : ' (exclusive)'}`;\n }\n case 'too_big': {\n const i = issue as unknown as TooBigIssueV4;\n return `Value too large — maximum is ${String(i.maximum)}${i.inclusive ? ' (inclusive)' : ' (exclusive)'}`;\n }\n case 'unrecognized_keys': {\n const i = issue as unknown as UnrecognizedKeysIssueV4;\n return `Unrecognized keys: ${i.keys.join(', ')}`;\n }\n default:\n return issue.message;\n }\n}\n\nfunction getActionableHint(issue: z.ZodIssue, fieldPath: string, fieldSchema: ZodLike | undefined): string | undefined {\n const flag = `--${fieldPath}`;\n const code = issue.code as string;\n\n switch (code) {\n case 'invalid_type': {\n const i = issue as unknown as InvalidTypeIssueV4;\n const received = extractReceived(i.message);\n\n if (received === 'undefined') {\n const typeLabel = fieldSchema ? describeType(fieldSchema) : 'value';\n return `Provide: ${flag} <${typeLabel}>`;\n }\n\n if (received === 'string' && (i.expected === 'record' || i.expected === 'array' || i.expected === 'object')) {\n return `Received a JSON string instead of ${i.expected}.\\n → The coercion layer should handle this automatically.\\n → CLI usage: ${flag} '<json ${i.expected}>'`;\n }\n\n return undefined;\n }\n\n case 'invalid_value': {\n const i = issue as unknown as InvalidValueIssueV4;\n const example = i.values[0];\n return `Use: ${flag} ${String(example)}`;\n }\n\n default:\n return undefined;\n }\n}\n\nfunction getFieldSchema(pathSegments: string[], schema: z.ZodObject<z.ZodRawShape>): ZodLike | undefined {\n if (pathSegments.length === 0) return undefined;\n return schema.shape[pathSegments[0]] as unknown as ZodLike | undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Converts a ZodError into a multi-line string optimized for AI agents.\n *\n * Each field with errors shows:\n * - field name, whether it is required/optional, and its expected type\n * - a concise description of what went wrong\n * - a concrete actionable hint (e.g. CLI flag usage)\n *\n * Detecting stringified objects: when the error says \"expected record/array,\n * received string\", it calls out the common Claude Code serialisation issue\n * and explains that the coercion layer should handle it automatically.\n *\n * @example\n * try {\n * schema.parse(args);\n * } catch (err) {\n * if (err instanceof z.ZodError) {\n * console.error(formatZodError(err, { schemaName: 'run_spec', schema }));\n * }\n * }\n */\nexport function formatZodError(\n error: z.ZodError,\n options?: { schemaName?: string; schema?: z.ZodObject<z.ZodRawShape> },\n): string {\n const { schemaName, schema } = options ?? {};\n\n // Group issues by dotted path\n const byPath = new Map<string, z.ZodIssue[]>();\n for (const issue of error.issues) {\n const path = issue.path.length > 0 ? issue.path.map(String).join('.') : '(root)';\n const existing = byPath.get(path) ?? [];\n existing.push(issue);\n byPath.set(path, existing);\n }\n\n const header = schemaName ? `Validation failed for \"${schemaName}\":` : 'Validation failed:';\n const lines: string[] = [header];\n\n for (const [path, issues] of byPath) {\n lines.push('');\n\n const fieldSchema = schema ? getFieldSchema(path.split('.'), schema) : undefined;\n const required = fieldSchema\n ? isRequired(fieldSchema)\n : issues.some((i) => {\n if ((i.code as string) !== 'invalid_type') return false;\n const msg = (i as unknown as { message: string }).message;\n return extractReceived(msg) === 'undefined';\n });\n\n const typeDesc = fieldSchema ? describeType(fieldSchema) : '';\n const meta = `(${required ? 'required' : 'optional'})${typeDesc ? ` — ${typeDesc}` : ''}`;\n\n lines.push(` • ${path} ${meta}`);\n\n for (const issue of issues) {\n lines.push(` ✗ ${formatIssueMessage(issue)}`);\n const hint = getActionableHint(issue, path, fieldSchema);\n if (hint) {\n lines.push(` → ${hint}`);\n }\n }\n }\n\n return lines.join('\\n');\n}\n","import { z } from 'zod';\nimport type { CliArgDefinition, CliArgType, CliArgsResult } from '../types/index.js';\nimport { describeType } from './formatZodError.js';\n\n// ---------------------------------------------------------------------------\n// Internal helpers — Zod v4 compatible\n// ---------------------------------------------------------------------------\n\n// Structural interface compatible with both $ZodType (internal) and ZodType (public)\ninterface ZodLike {\n _def: { type?: string; innerType?: ZodLike; defaultValue?: unknown; options?: readonly ZodLike[] };\n description?: string;\n}\n\nfunction defType(schema: ZodLike): string {\n return schema._def.type ?? '';\n}\n\nfunction defInnerType(schema: ZodLike): ZodLike | undefined {\n return schema._def.innerType;\n}\n\nfunction unwrapSchema(schema: ZodLike): ZodLike {\n const t = defType(schema);\n if (t === 'optional' || t === 'nullable' || t === 'default') {\n const inner = defInnerType(schema);\n return inner ? unwrapSchema(inner) : schema;\n }\n return schema;\n}\n\nfunction isRequired(schema: ZodLike): boolean {\n const t = defType(schema);\n return t !== 'optional' && t !== 'default';\n}\n\nfunction getDefault(schema: ZodLike): unknown {\n if (defType(schema) === 'default') {\n return schema._def.defaultValue;\n }\n return undefined;\n}\n\nfunction getDescription(schema: ZodLike): string {\n return schema.description ?? '';\n}\n\n/**\n * Maps a Zod schema field to a CliArgType used for help text and parsing.\n */\nfunction resolveCliType(schema: ZodLike): CliArgType {\n const core = unwrapSchema(schema);\n const t = defType(core);\n\n switch (t) {\n case 'boolean':\n return 'boolean';\n case 'number':\n return 'number';\n case 'object':\n case 'record':\n case 'array':\n return 'json';\n case 'union': {\n const opts: readonly ZodLike[] = core._def.options ?? [];\n const hasNonPrimitive = opts.some((o) => {\n const ot = defType(unwrapSchema(o));\n return ot === 'object' || ot === 'array' || ot === 'record';\n });\n return hasNonPrimitive ? 'json' : 'string';\n }\n default:\n return 'string';\n }\n}\n\n/**\n * Returns enum choices if the (unwrapped) schema is a ZodEnum.\n */\nfunction getChoices(schema: ZodLike): string[] | undefined {\n const core = unwrapSchema(schema);\n if (defType(core) === 'enum') {\n return (core as unknown as { options: string[] }).options;\n }\n return undefined;\n}\n\n/**\n * Builds the value placeholder shown in help text, e.g. '<string>', '<json>',\n * '<playwright|extension>'.\n */\nfunction buildValuePlaceholder(argType: CliArgType, choices?: string[]): string {\n if (choices && choices.length > 0) return `<${choices.join('|')}>`;\n switch (argType) {\n case 'boolean':\n return '';\n case 'number':\n return '<number>';\n case 'json':\n return '<json>';\n default:\n return '<string>';\n }\n}\n\n/**\n * Converts a single schema field to a CliArgDefinition.\n */\nfunction fieldToCliArg(key: string, schema: ZodLike): CliArgDefinition {\n const argType = resolveCliType(schema);\n const choices = getChoices(schema);\n const defaultVal = getDefault(schema);\n const desc = getDescription(schema);\n\n return {\n flag: `--${key}`,\n type: argType,\n required: isRequired(schema),\n description: desc,\n default: defaultVal,\n choices,\n typeLabel: describeType(schema),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Help text formatting\n// ---------------------------------------------------------------------------\n\nconst COL_WIDTH = 36;\n\nfunction padEnd(str: string, width: number): string {\n return str.length >= width ? `${str} ` : str.padEnd(width);\n}\n\nfunction renderArg(arg: CliArgDefinition): string {\n const placeholder = buildValuePlaceholder(arg.type, arg.choices);\n const flagPart = placeholder ? `${arg.flag} ${placeholder}` : arg.flag;\n\n const typeAnnotation = arg.type === 'json' ? ` — ${arg.typeLabel}` : '';\n const defaultAnnotation = arg.default !== undefined ? ` [default: ${JSON.stringify(arg.default)}]` : '';\n const description = `${arg.description}${typeAnnotation}${defaultAnnotation}`.trim();\n\n return ` ${padEnd(flagPart, COL_WIDTH)}${description}`;\n}\n\nfunction formatHelp(args: CliArgDefinition[], options: { command?: string; description?: string }): string {\n const lines: string[] = [];\n\n const commandName = options.command ?? '<tool>';\n lines.push(`Usage: ${commandName} [options]`);\n\n if (options.description) {\n lines.push('');\n lines.push(options.description);\n }\n\n const required = args.filter((a) => a.required);\n const optional = args.filter((a) => !a.required);\n\n if (required.length > 0) {\n lines.push('');\n lines.push('Required:');\n for (const arg of required) {\n lines.push(renderArg(arg));\n }\n }\n\n if (optional.length > 0) {\n lines.push('');\n lines.push('Optional:');\n for (const arg of optional) {\n lines.push(renderArg(arg));\n }\n }\n\n return lines.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Converts a ZodObject schema to:\n * - `args`: structured CliArgDefinition[] for programmatic use (e.g. parsing)\n * - `help`: formatted help string equivalent to `--help` output\n *\n * Enables AI agents to inspect a tool's expected arguments as CLI flags,\n * then reconstruct a valid call using {@link cliArgsToObject}.\n *\n * @example\n * const { help } = zodToCliArgs(RunSpecToolInputSchema, { command: 'run_spec' });\n * console.log(help);\n * // Usage: run_spec [options]\n * //\n * // Required:\n * // --specPath <string> Absolute path to the spec file\n * //\n * // Optional:\n * // --headless Run in headless mode [default: true]\n * // --env <json> Environment variables — Record<string, string>\n */\nexport function zodToCliArgs(\n schema: z.ZodObject<z.ZodRawShape>,\n options?: { command?: string; description?: string },\n): CliArgsResult {\n const args = Object.entries(schema.shape).map(([key, fieldSchema]) =>\n fieldToCliArg(key, fieldSchema as unknown as ZodLike),\n );\n\n const help = formatHelp(args, options ?? {});\n\n return { args, help };\n}\n","import { z } from 'zod';\nimport { zodToCliArgs } from './zodToCliArgs.js';\n\n// ---------------------------------------------------------------------------\n// Key normalisation\n// ---------------------------------------------------------------------------\n\n/**\n * Converts a CLI flag name (without --) to a camelCase object key.\n * Supports both kebab-case and camelCase input:\n * 'spec-path' → 'specPath'\n * 'specPath' → 'specPath'\n * 'base-url' → 'baseURL' (only uppercases the first letter after -)\n */\nfunction flagToKey(flag: string): string {\n // strip leading -- if present\n const raw = flag.startsWith('--') ? flag.slice(2) : flag;\n // kebab-case → camelCase\n return raw.replace(/-([a-z])/gi, (_, c: string) => c.toUpperCase());\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Parses a CLI argv array (e.g. process.argv.slice(2)) into a\n * Record<string, unknown> that can be validated by a Zod schema.\n *\n * Uses the schema to determine which flags are booleans (no value expected)\n * and which expect a JSON value (auto-parsed). The result can be passed\n * directly to {@link coerceArgs} or schema.parse().\n *\n * Parsing rules:\n * --flag (boolean in schema) → { flag: true }\n * --no-flag → { flag: false }\n * --key value (json in schema) → { key: JSON.parse(value) }\n * --key value (number in schema) → { key: parseFloat(value) }\n * --key value (string/default) → { key: value }\n * Kebab-case flags are converted to camelCase automatically.\n *\n * @example\n * const obj = cliArgsToObject(\n * ['--specPath', '/tests/foo.spec.ts', '--headless', '--env', '{\"KEY\":\"val\"}'],\n * RunSpecToolInputSchema,\n * );\n * // { specPath: '/tests/foo.spec.ts', headless: true, env: { KEY: 'val' } }\n */\nexport function cliArgsToObject(argv: string[], schema: z.ZodObject<z.ZodRawShape>): Record<string, unknown> {\n const { args: argDefs } = zodToCliArgs(schema);\n\n // Build lookup maps: both camelCase and kebab forms → CliArgDefinition\n const byKey = new Map(argDefs.map((d) => [flagToKey(d.flag), d]));\n // Also support kebab-case lookups (the flag already starts with --)\n const byFlag = new Map(argDefs.map((d) => [d.flag, d]));\n\n const result: Record<string, unknown> = {};\n\n let i = 0;\n while (i < argv.length) {\n const token = argv[i];\n\n if (!token.startsWith('--')) {\n i++;\n continue;\n }\n\n // Handle --no-<flag> negation\n if (token.startsWith('--no-')) {\n const key = flagToKey(token.slice(5)); // strip --no-\n result[key] = false;\n i++;\n continue;\n }\n\n // Support --key=value syntax\n const eqIdx = token.indexOf('=');\n let flagToken: string;\n let inlineValue: string | undefined;\n\n if (eqIdx !== -1) {\n flagToken = token.slice(0, eqIdx);\n inlineValue = token.slice(eqIdx + 1);\n } else {\n flagToken = token;\n inlineValue = undefined;\n }\n\n const key = flagToKey(flagToken);\n const argDef = byKey.get(key) ?? byFlag.get(flagToken);\n\n // Boolean flags: presence alone means true\n if (argDef?.type === 'boolean') {\n result[key] = true;\n i++;\n continue;\n }\n\n // Determine the value: inline (--key=val) or next token\n let rawValue: string | undefined;\n if (inlineValue !== undefined) {\n rawValue = inlineValue;\n i++;\n } else if (i + 1 < argv.length && !argv[i + 1].startsWith('--')) {\n rawValue = argv[i + 1];\n i += 2;\n } else {\n // No value token following — treat as boolean true\n result[key] = true;\n i++;\n continue;\n }\n\n // Parse value based on schema type\n if (argDef?.type === 'json') {\n try {\n result[key] = JSON.parse(rawValue);\n } catch {\n result[key] = rawValue;\n }\n } else if (argDef?.type === 'number') {\n const parsed = Number.parseFloat(rawValue);\n result[key] = Number.isNaN(parsed) ? rawValue : parsed;\n } else {\n result[key] = rawValue;\n }\n }\n\n return result;\n}\n","import { z } from 'zod';\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\ntype JsonSchemaNode = Record<string, unknown>;\n\n/**\n * Convert a single JSON Schema property node to a Zod type.\n * Handles: string, number, integer, boolean, null, array, object,\n * anyOf/oneOf, enum, and array-of-types (e.g. [\"string\",\"null\"]).\n */\nfunction propertyToZod(node: unknown): z.ZodTypeAny {\n if (!node || typeof node !== 'object' || Array.isArray(node)) return z.unknown();\n const n = node as JsonSchemaNode;\n\n // anyOf / oneOf → union\n const variants = (n.anyOf ?? n.oneOf) as unknown[] | undefined;\n if (Array.isArray(variants) && variants.length > 0) {\n const members = variants.map(propertyToZod);\n if (members.length === 1) return members[0];\n return z.union([members[0], members[1], ...members.slice(2)] as [z.ZodTypeAny, z.ZodTypeAny, ...z.ZodTypeAny[]]);\n }\n\n // enum\n if (Array.isArray(n.enum) && n.enum.every((v) => typeof v === 'string')) {\n const [first, second, ...rest] = n.enum as string[];\n if (first === undefined) return z.unknown();\n if (second === undefined) return z.literal(first);\n return z.enum([first, second, ...rest]);\n }\n\n const type = n.type;\n\n // Array-of-types: [\"string\", \"null\"] → optional string\n if (Array.isArray(type)) {\n const nonNull = type.filter((t) => t !== 'null') as string[];\n const nullable = type.includes('null');\n if (nonNull.length === 0) return nullable ? z.null() : z.unknown();\n const inner =\n nonNull.length === 1\n ? propertyToZod({ ...n, type: nonNull[0] })\n : z.union(\n nonNull.map((t) => propertyToZod({ ...n, type: t })) as [z.ZodTypeAny, z.ZodTypeAny, ...z.ZodTypeAny[]],\n );\n return nullable ? z.union([inner, z.null()]) : inner;\n }\n\n if (type === 'string') return z.string();\n if (type === 'number' || type === 'integer') return z.number();\n if (type === 'boolean') return z.boolean();\n if (type === 'null') return z.null();\n\n if (type === 'array') {\n const items = n.items ? propertyToZod(n.items) : z.unknown();\n return z.array(items);\n }\n\n if (type === 'object') {\n if (n.properties && typeof n.properties === 'object' && !Array.isArray(n.properties)) {\n return jsonSchemaToZod(n);\n }\n return z.record(z.string(), z.unknown());\n }\n\n return z.unknown();\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Convert a JSON Schema object definition to a Zod object schema.\n *\n * Handles `properties`, `required`, `anyOf`/`oneOf`, `enum`, and the\n * common scalar types. Fields not listed in `required` are made optional.\n * Unknown/unsupported nodes map to `z.unknown()`.\n *\n * This is intentionally non-exhaustive: the goal is accurate type\n * classification for coercion (primitive vs non-primitive), not strict\n * schema validation.\n *\n * @example\n * const schema = jsonSchemaToZod({\n * type: 'object',\n * properties: {\n * env: { type: 'object' },\n * headless: { type: 'boolean' },\n * },\n * required: ['env'],\n * });\n * // schema.shape.env → ZodRecord (non-primitive → will be JSON.parsed if string)\n * // schema.shape.headless → ZodOptional<ZodBoolean>\n */\nexport function jsonSchemaToZod(schema: Record<string, unknown>): z.ZodObject<z.ZodRawShape> {\n const properties = schema.properties as Record<string, unknown> | undefined;\n const required = new Set<string>(Array.isArray(schema.required) ? (schema.required as string[]) : []);\n\n if (!properties) return z.object({});\n\n const shape: Record<string, z.ZodTypeAny> = {};\n for (const [key, prop] of Object.entries(properties)) {\n const zodType = propertyToZod(prop);\n shape[key] = required.has(key) ? zodType : zodType.optional();\n }\n\n return z.object(shape);\n}\n"],"mappings":"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"}
@@ -0,0 +1,181 @@
1
+ import { z } from "zod";
2
+
3
+ //#region src/types/index.d.ts
4
+
5
+ /**
6
+ * Types for foundation-validator utilities
7
+ */
8
+ /**
9
+ * The CLI type to use when parsing and displaying an argument.
10
+ * - 'string': plain string value
11
+ * - 'number': numeric value (parsed via parseFloat)
12
+ * - 'boolean': flag with no value (presence = true, --no-flag = false)
13
+ * - 'json': JSON-encoded object or array
14
+ */
15
+ type CliArgType = 'string' | 'number' | 'boolean' | 'json';
16
+ /**
17
+ * A single CLI argument definition derived from a Zod schema field.
18
+ */
19
+ interface CliArgDefinition {
20
+ /** CLI flag including -- prefix, e.g. '--specPath' */
21
+ flag: string;
22
+ /** Argument value type for parsing */
23
+ type: CliArgType;
24
+ /** Whether this argument is required */
25
+ required: boolean;
26
+ /** Human-readable description */
27
+ description: string;
28
+ /** Default value if any */
29
+ default?: unknown;
30
+ /** Valid choices for enum fields */
31
+ choices?: string[];
32
+ /** Human-readable type label for help text, e.g. 'Record<string, string>' */
33
+ typeLabel: string;
34
+ }
35
+ /**
36
+ * Result of converting a Zod schema to CLI arg definitions.
37
+ */
38
+ interface CliArgsResult {
39
+ /** Structured arg definitions for programmatic use */
40
+ args: CliArgDefinition[];
41
+ /** Formatted help string for display (equivalent of --help output) */
42
+ help: string;
43
+ }
44
+ //#endregion
45
+ //#region src/utils/coerceArgs.d.ts
46
+ /**
47
+ * Walks a ZodObject's shape and, for any field that expects a non-primitive
48
+ * type (object, array, record, or union containing one), attempts to
49
+ * JSON.parse string values. Leaves the value unchanged if:
50
+ * - it is not a string
51
+ * - the schema expects a primitive
52
+ * - the string is not valid JSON
53
+ *
54
+ * This handles the common Claude Code behaviour of stringifying nested args
55
+ * (e.g. env: '{"KEY":"val"}' instead of env: { KEY: 'val' }).
56
+ */
57
+ declare function coerceArgs(args: Record<string, unknown>, schema: z.ZodObject<z.ZodRawShape>): Record<string, unknown>;
58
+ //#endregion
59
+ //#region src/utils/formatZodError.d.ts
60
+ interface ZodLike {
61
+ _def: {
62
+ type?: string;
63
+ innerType?: ZodLike;
64
+ element?: ZodLike;
65
+ valueType?: ZodLike;
66
+ options?: readonly ZodLike[];
67
+ value?: unknown;
68
+ };
69
+ description?: string;
70
+ }
71
+ /**
72
+ * Produces a concise human-readable type label for a Zod schema.
73
+ * Examples: 'string', 'string[]', 'Record<string, string>', 'enum [a, b]'
74
+ */
75
+ declare function describeType(schema: ZodLike): string;
76
+ /**
77
+ * Converts a ZodError into a multi-line string optimized for AI agents.
78
+ *
79
+ * Each field with errors shows:
80
+ * - field name, whether it is required/optional, and its expected type
81
+ * - a concise description of what went wrong
82
+ * - a concrete actionable hint (e.g. CLI flag usage)
83
+ *
84
+ * Detecting stringified objects: when the error says "expected record/array,
85
+ * received string", it calls out the common Claude Code serialisation issue
86
+ * and explains that the coercion layer should handle it automatically.
87
+ *
88
+ * @example
89
+ * try {
90
+ * schema.parse(args);
91
+ * } catch (err) {
92
+ * if (err instanceof z.ZodError) {
93
+ * console.error(formatZodError(err, { schemaName: 'run_spec', schema }));
94
+ * }
95
+ * }
96
+ */
97
+ declare function formatZodError(error: z.ZodError, options?: {
98
+ schemaName?: string;
99
+ schema?: z.ZodObject<z.ZodRawShape>;
100
+ }): string;
101
+ //#endregion
102
+ //#region src/utils/zodToCliArgs.d.ts
103
+ /**
104
+ * Converts a ZodObject schema to:
105
+ * - `args`: structured CliArgDefinition[] for programmatic use (e.g. parsing)
106
+ * - `help`: formatted help string equivalent to `--help` output
107
+ *
108
+ * Enables AI agents to inspect a tool's expected arguments as CLI flags,
109
+ * then reconstruct a valid call using {@link cliArgsToObject}.
110
+ *
111
+ * @example
112
+ * const { help } = zodToCliArgs(RunSpecToolInputSchema, { command: 'run_spec' });
113
+ * console.log(help);
114
+ * // Usage: run_spec [options]
115
+ * //
116
+ * // Required:
117
+ * // --specPath <string> Absolute path to the spec file
118
+ * //
119
+ * // Optional:
120
+ * // --headless Run in headless mode [default: true]
121
+ * // --env <json> Environment variables — Record<string, string>
122
+ */
123
+ declare function zodToCliArgs(schema: z.ZodObject<z.ZodRawShape>, options?: {
124
+ command?: string;
125
+ description?: string;
126
+ }): CliArgsResult;
127
+ //#endregion
128
+ //#region src/utils/cliArgsToObject.d.ts
129
+ /**
130
+ * Parses a CLI argv array (e.g. process.argv.slice(2)) into a
131
+ * Record<string, unknown> that can be validated by a Zod schema.
132
+ *
133
+ * Uses the schema to determine which flags are booleans (no value expected)
134
+ * and which expect a JSON value (auto-parsed). The result can be passed
135
+ * directly to {@link coerceArgs} or schema.parse().
136
+ *
137
+ * Parsing rules:
138
+ * --flag (boolean in schema) → { flag: true }
139
+ * --no-flag → { flag: false }
140
+ * --key value (json in schema) → { key: JSON.parse(value) }
141
+ * --key value (number in schema) → { key: parseFloat(value) }
142
+ * --key value (string/default) → { key: value }
143
+ * Kebab-case flags are converted to camelCase automatically.
144
+ *
145
+ * @example
146
+ * const obj = cliArgsToObject(
147
+ * ['--specPath', '/tests/foo.spec.ts', '--headless', '--env', '{"KEY":"val"}'],
148
+ * RunSpecToolInputSchema,
149
+ * );
150
+ * // { specPath: '/tests/foo.spec.ts', headless: true, env: { KEY: 'val' } }
151
+ */
152
+ declare function cliArgsToObject(argv: string[], schema: z.ZodObject<z.ZodRawShape>): Record<string, unknown>;
153
+ //#endregion
154
+ //#region src/utils/jsonSchemaToZod.d.ts
155
+ /**
156
+ * Convert a JSON Schema object definition to a Zod object schema.
157
+ *
158
+ * Handles `properties`, `required`, `anyOf`/`oneOf`, `enum`, and the
159
+ * common scalar types. Fields not listed in `required` are made optional.
160
+ * Unknown/unsupported nodes map to `z.unknown()`.
161
+ *
162
+ * This is intentionally non-exhaustive: the goal is accurate type
163
+ * classification for coercion (primitive vs non-primitive), not strict
164
+ * schema validation.
165
+ *
166
+ * @example
167
+ * const schema = jsonSchemaToZod({
168
+ * type: 'object',
169
+ * properties: {
170
+ * env: { type: 'object' },
171
+ * headless: { type: 'boolean' },
172
+ * },
173
+ * required: ['env'],
174
+ * });
175
+ * // schema.shape.env → ZodRecord (non-primitive → will be JSON.parsed if string)
176
+ * // schema.shape.headless → ZodOptional<ZodBoolean>
177
+ */
178
+ declare function jsonSchemaToZod(schema: Record<string, unknown>): z.ZodObject<z.ZodRawShape>;
179
+ //#endregion
180
+ export { CliArgDefinition, CliArgType, CliArgsResult, cliArgsToObject, coerceArgs, describeType, formatZodError, jsonSchemaToZod, zodToCliArgs };
181
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/types/index.ts","../src/utils/coerceArgs.ts","../src/utils/formatZodError.ts","../src/utils/zodToCliArgs.ts","../src/utils/cliArgsToObject.ts","../src/utils/jsonSchemaToZod.ts"],"sourcesContent":[],"mappings":";;;;;;;AAWA;AAKA;AAoBA;;;;ACcA;AAAiC,KDvCrB,UAAA,GCuCqB,QAAA,GAAA,QAAA,GAAA,SAAA,GAAA,MAAA;;;;AAAoE,UDlCpF,gBAAA,CCkCoF;;;;EC3C3F,IAAA,EFaF,UEbS;EAGD;EACF,QAAA,EAAA,OAAA;EACE;EACO,WAAA,EAAA,MAAA;EAAO;EAuBd,OAAA,CAAA,EAAA,OAAY;EAgMZ;EACL,OAAA,CAAA,EAAA,MAAA,EAAA;EAC+C;EAAZ,SAAA,EAAA,MAAA;;;;;AC3B9B,UHvKC,aAAA,CGuKW;EACJ;EAAZ,IAAA,EHtKJ,gBGsKI,EAAA;EAET;EAAa,IAAA,EAAA,MAAA;;;;;;AHnMhB;AAKA;AAoBA;;;;ACcA;;;AAAoE,iBAApD,UAAA,CAAoD,IAAA,EAAnC,MAAmC,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,MAAA,EAAF,CAAA,CAAE,SAAA,CAAU,CAAA,CAAE,WAAZ,CAAA,CAAA,EAA2B,MAA3B,CAAA,MAAA,EAAA,OAAA,CAAA;;;UC3C1D,OAAA;;IFIE,IAAA,CAAA,EAAA,MAAU;IAKL,SAAA,CAAA,EEND,OFMiB;IAoBhB,OAAA,CAAA,EEzBH,OFyBgB;gBExBd;uBACO;;EDqCP,CAAA;EAAiB,WAAA,CAAA,EAAA,MAAA;;;;;;iBCdjB,YAAA,SAAqB;;AApCb;;;;;;AAoCxB;AAgMA;;;;;;;;ACzBA;;;;;iBDyBgB,cAAA,QACP,CAAA,CAAE,iBErLX;;WFsL4C,CAAA,CAAE,UAAU,CAAA,CAAE;AEtL1D,CAAA,CAAA,EAAgB,MAAA;;;;AJrChB;AAKA;AAoBA;;;;ACcA;;;;;;;;;AClDwB;;;;AAaD,iBC8LP,YAAA,CD9LO,MAAA,EC+Lb,CAAA,CAAE,SD/LW,CC+LD,CAAA,CAAE,WD/LD,CAAA,EAAA,OAuNvB,CAvNuB,EAAA;EAAO,OAAA,CAAA,EAAA,MAAA;EAuBd,WAAA,CAAA,EAAA,MAAY;AAgM5B,CAAA,CAAA,ECtBG,aDsBa;;;;;AFzNhB;AAKA;AAoBA;;;;ACcA;;;;;;;;;AClDwB;;;;;;AAoCR,iBEYA,eAAA,CFZ4B,IAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EEYY,CAAA,CAAE,SFZd,CEYwB,CAAA,CAAE,WFZ1B,CAAA,CAAA,EEYyC,MFZzC,CAAA,MAAA,EAAA,OAAA,CAAA;;;;;AFzB5C;AAKA;AAoBA;;;;ACcA;;;;;;;;;AClDwB;;;;;;AAoCR,iBG4DA,eAAA,CH5D4B,MAAA,EG4DJ,MH5DI,CAAA,MAAA,EAAA,OAAA,CAAA,CAAA,EG4DsB,CAAA,CAAE,SH5DxB,CG4DkC,CAAA,CAAE,WH5DpC,CAAA"}
@@ -0,0 +1,181 @@
1
+ import { z } from "zod";
2
+
3
+ //#region src/types/index.d.ts
4
+
5
+ /**
6
+ * Types for foundation-validator utilities
7
+ */
8
+ /**
9
+ * The CLI type to use when parsing and displaying an argument.
10
+ * - 'string': plain string value
11
+ * - 'number': numeric value (parsed via parseFloat)
12
+ * - 'boolean': flag with no value (presence = true, --no-flag = false)
13
+ * - 'json': JSON-encoded object or array
14
+ */
15
+ type CliArgType = 'string' | 'number' | 'boolean' | 'json';
16
+ /**
17
+ * A single CLI argument definition derived from a Zod schema field.
18
+ */
19
+ interface CliArgDefinition {
20
+ /** CLI flag including -- prefix, e.g. '--specPath' */
21
+ flag: string;
22
+ /** Argument value type for parsing */
23
+ type: CliArgType;
24
+ /** Whether this argument is required */
25
+ required: boolean;
26
+ /** Human-readable description */
27
+ description: string;
28
+ /** Default value if any */
29
+ default?: unknown;
30
+ /** Valid choices for enum fields */
31
+ choices?: string[];
32
+ /** Human-readable type label for help text, e.g. 'Record<string, string>' */
33
+ typeLabel: string;
34
+ }
35
+ /**
36
+ * Result of converting a Zod schema to CLI arg definitions.
37
+ */
38
+ interface CliArgsResult {
39
+ /** Structured arg definitions for programmatic use */
40
+ args: CliArgDefinition[];
41
+ /** Formatted help string for display (equivalent of --help output) */
42
+ help: string;
43
+ }
44
+ //#endregion
45
+ //#region src/utils/coerceArgs.d.ts
46
+ /**
47
+ * Walks a ZodObject's shape and, for any field that expects a non-primitive
48
+ * type (object, array, record, or union containing one), attempts to
49
+ * JSON.parse string values. Leaves the value unchanged if:
50
+ * - it is not a string
51
+ * - the schema expects a primitive
52
+ * - the string is not valid JSON
53
+ *
54
+ * This handles the common Claude Code behaviour of stringifying nested args
55
+ * (e.g. env: '{"KEY":"val"}' instead of env: { KEY: 'val' }).
56
+ */
57
+ declare function coerceArgs(args: Record<string, unknown>, schema: z.ZodObject<z.ZodRawShape>): Record<string, unknown>;
58
+ //#endregion
59
+ //#region src/utils/formatZodError.d.ts
60
+ interface ZodLike {
61
+ _def: {
62
+ type?: string;
63
+ innerType?: ZodLike;
64
+ element?: ZodLike;
65
+ valueType?: ZodLike;
66
+ options?: readonly ZodLike[];
67
+ value?: unknown;
68
+ };
69
+ description?: string;
70
+ }
71
+ /**
72
+ * Produces a concise human-readable type label for a Zod schema.
73
+ * Examples: 'string', 'string[]', 'Record<string, string>', 'enum [a, b]'
74
+ */
75
+ declare function describeType(schema: ZodLike): string;
76
+ /**
77
+ * Converts a ZodError into a multi-line string optimized for AI agents.
78
+ *
79
+ * Each field with errors shows:
80
+ * - field name, whether it is required/optional, and its expected type
81
+ * - a concise description of what went wrong
82
+ * - a concrete actionable hint (e.g. CLI flag usage)
83
+ *
84
+ * Detecting stringified objects: when the error says "expected record/array,
85
+ * received string", it calls out the common Claude Code serialisation issue
86
+ * and explains that the coercion layer should handle it automatically.
87
+ *
88
+ * @example
89
+ * try {
90
+ * schema.parse(args);
91
+ * } catch (err) {
92
+ * if (err instanceof z.ZodError) {
93
+ * console.error(formatZodError(err, { schemaName: 'run_spec', schema }));
94
+ * }
95
+ * }
96
+ */
97
+ declare function formatZodError(error: z.ZodError, options?: {
98
+ schemaName?: string;
99
+ schema?: z.ZodObject<z.ZodRawShape>;
100
+ }): string;
101
+ //#endregion
102
+ //#region src/utils/zodToCliArgs.d.ts
103
+ /**
104
+ * Converts a ZodObject schema to:
105
+ * - `args`: structured CliArgDefinition[] for programmatic use (e.g. parsing)
106
+ * - `help`: formatted help string equivalent to `--help` output
107
+ *
108
+ * Enables AI agents to inspect a tool's expected arguments as CLI flags,
109
+ * then reconstruct a valid call using {@link cliArgsToObject}.
110
+ *
111
+ * @example
112
+ * const { help } = zodToCliArgs(RunSpecToolInputSchema, { command: 'run_spec' });
113
+ * console.log(help);
114
+ * // Usage: run_spec [options]
115
+ * //
116
+ * // Required:
117
+ * // --specPath <string> Absolute path to the spec file
118
+ * //
119
+ * // Optional:
120
+ * // --headless Run in headless mode [default: true]
121
+ * // --env <json> Environment variables — Record<string, string>
122
+ */
123
+ declare function zodToCliArgs(schema: z.ZodObject<z.ZodRawShape>, options?: {
124
+ command?: string;
125
+ description?: string;
126
+ }): CliArgsResult;
127
+ //#endregion
128
+ //#region src/utils/cliArgsToObject.d.ts
129
+ /**
130
+ * Parses a CLI argv array (e.g. process.argv.slice(2)) into a
131
+ * Record<string, unknown> that can be validated by a Zod schema.
132
+ *
133
+ * Uses the schema to determine which flags are booleans (no value expected)
134
+ * and which expect a JSON value (auto-parsed). The result can be passed
135
+ * directly to {@link coerceArgs} or schema.parse().
136
+ *
137
+ * Parsing rules:
138
+ * --flag (boolean in schema) → { flag: true }
139
+ * --no-flag → { flag: false }
140
+ * --key value (json in schema) → { key: JSON.parse(value) }
141
+ * --key value (number in schema) → { key: parseFloat(value) }
142
+ * --key value (string/default) → { key: value }
143
+ * Kebab-case flags are converted to camelCase automatically.
144
+ *
145
+ * @example
146
+ * const obj = cliArgsToObject(
147
+ * ['--specPath', '/tests/foo.spec.ts', '--headless', '--env', '{"KEY":"val"}'],
148
+ * RunSpecToolInputSchema,
149
+ * );
150
+ * // { specPath: '/tests/foo.spec.ts', headless: true, env: { KEY: 'val' } }
151
+ */
152
+ declare function cliArgsToObject(argv: string[], schema: z.ZodObject<z.ZodRawShape>): Record<string, unknown>;
153
+ //#endregion
154
+ //#region src/utils/jsonSchemaToZod.d.ts
155
+ /**
156
+ * Convert a JSON Schema object definition to a Zod object schema.
157
+ *
158
+ * Handles `properties`, `required`, `anyOf`/`oneOf`, `enum`, and the
159
+ * common scalar types. Fields not listed in `required` are made optional.
160
+ * Unknown/unsupported nodes map to `z.unknown()`.
161
+ *
162
+ * This is intentionally non-exhaustive: the goal is accurate type
163
+ * classification for coercion (primitive vs non-primitive), not strict
164
+ * schema validation.
165
+ *
166
+ * @example
167
+ * const schema = jsonSchemaToZod({
168
+ * type: 'object',
169
+ * properties: {
170
+ * env: { type: 'object' },
171
+ * headless: { type: 'boolean' },
172
+ * },
173
+ * required: ['env'],
174
+ * });
175
+ * // schema.shape.env → ZodRecord (non-primitive → will be JSON.parsed if string)
176
+ * // schema.shape.headless → ZodOptional<ZodBoolean>
177
+ */
178
+ declare function jsonSchemaToZod(schema: Record<string, unknown>): z.ZodObject<z.ZodRawShape>;
179
+ //#endregion
180
+ export { CliArgDefinition, CliArgType, CliArgsResult, cliArgsToObject, coerceArgs, describeType, formatZodError, jsonSchemaToZod, zodToCliArgs };
181
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types/index.ts","../src/utils/coerceArgs.ts","../src/utils/formatZodError.ts","../src/utils/zodToCliArgs.ts","../src/utils/cliArgsToObject.ts","../src/utils/jsonSchemaToZod.ts"],"sourcesContent":[],"mappings":";;;;;;;AAWA;AAKA;AAoBA;;;;ACcA;AAAiC,KDvCrB,UAAA,GCuCqB,QAAA,GAAA,QAAA,GAAA,SAAA,GAAA,MAAA;;;;AAAoE,UDlCpF,gBAAA,CCkCoF;;;;EC3C3F,IAAA,EFaF,UEbS;EAGD;EACF,QAAA,EAAA,OAAA;EACE;EACO,WAAA,EAAA,MAAA;EAAO;EAuBd,OAAA,CAAA,EAAA,OAAY;EAgMZ;EACL,OAAA,CAAA,EAAA,MAAA,EAAA;EAC+C;EAAZ,SAAA,EAAA,MAAA;;;;;AC3B9B,UHvKC,aAAA,CGuKW;EACJ;EAAZ,IAAA,EHtKJ,gBGsKI,EAAA;EAET;EAAa,IAAA,EAAA,MAAA;;;;;;AHnMhB;AAKA;AAoBA;;;;ACcA;;;AAAoE,iBAApD,UAAA,CAAoD,IAAA,EAAnC,MAAmC,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,MAAA,EAAF,CAAA,CAAE,SAAA,CAAU,CAAA,CAAE,WAAZ,CAAA,CAAA,EAA2B,MAA3B,CAAA,MAAA,EAAA,OAAA,CAAA;;;UC3C1D,OAAA;;IFIE,IAAA,CAAA,EAAA,MAAU;IAKL,SAAA,CAAA,EEND,OFMiB;IAoBhB,OAAA,CAAA,EEzBH,OFyBgB;gBExBd;uBACO;;EDqCP,CAAA;EAAiB,WAAA,CAAA,EAAA,MAAA;;;;;;iBCdjB,YAAA,SAAqB;;AApCb;;;;;;AAoCxB;AAgMA;;;;;;;;ACzBA;;;;;iBDyBgB,cAAA,QACP,CAAA,CAAE,iBErLX;;WFsL4C,CAAA,CAAE,UAAU,CAAA,CAAE;AEtL1D,CAAA,CAAA,EAAgB,MAAA;;;;AJrChB;AAKA;AAoBA;;;;ACcA;;;;;;;;;AClDwB;;;;AAaD,iBC8LP,YAAA,CD9LO,MAAA,EC+Lb,CAAA,CAAE,SD/LW,CC+LD,CAAA,CAAE,WD/LD,CAAA,EAAA,OAuNvB,CAvNuB,EAAA;EAAO,OAAA,CAAA,EAAA,MAAA;EAuBd,WAAA,CAAA,EAAA,MAAY;AAgM5B,CAAA,CAAA,ECtBG,aDsBa;;;;;AFzNhB;AAKA;AAoBA;;;;ACcA;;;;;;;;;AClDwB;;;;;;AAoCR,iBEYA,eAAA,CFZ4B,IAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EEYY,CAAA,CAAE,SFZd,CEYwB,CAAA,CAAE,WFZ1B,CAAA,CAAA,EEYyC,MFZzC,CAAA,MAAA,EAAA,OAAA,CAAA;;;;;AFzB5C;AAKA;AAoBA;;;;ACcA;;;;;;;;;AClDwB;;;;;;AAoCR,iBG4DA,eAAA,CH5D4B,MAAA,EG4DJ,MH5DI,CAAA,MAAA,EAAA,OAAA,CAAA,CAAA,EG4DsB,CAAA,CAAE,SH5DxB,CG4DkC,CAAA,CAAE,WH5DpC,CAAA"}
package/dist/index.mjs ADDED
@@ -0,0 +1,4 @@
1
+ import{z as e}from"zod";function t(e){return e._def.type??``}function n(e){let r=t(e);if(r===`optional`||r===`nullable`||r===`default`){let t=e._def.innerType;return t?n(t):e}return e}function r(e){let i=n(e),a=t(i);return a===`object`||a===`array`||a===`record`?!0:a===`union`?(i._def.options??[]).some(r):!1}function i(e,t){let n={...e};for(let[e,i]of Object.entries(t.shape)){let t=n[e];if(typeof t==`string`&&r(i))try{n[e]=JSON.parse(t)}catch{}}return n}function a(e){return e._def.type??``}function o(e){return e._def.innerType}function s(e){let t=a(e);return t!==`optional`&&t!==`default`}function c(e){switch(a(e)){case`string`:return`string`;case`number`:return`number`;case`boolean`:return`boolean`;case`bigint`:return`bigint`;case`null`:return`null`;case`undefined`:return`undefined`;case`any`:return`any`;case`unknown`:return`unknown`;case`literal`:return JSON.stringify(e._def.value);case`enum`:return`enum [${(e.options??[]).join(`, `)}]`;case`array`:{let t=e._def.element;return t?`${c(t)}[]`:`unknown[]`}case`record`:{let t=e._def.valueType;return t?`Record<string, ${c(t)}>`:`Record<string, unknown>`}case`object`:return`object`;case`optional`:case`nullable`:case`default`:{let t=o(e);return t?c(t):`unknown`}case`union`:return(e._def.options??[]).map(c).join(` | `);default:return`unknown`}}function l(e){return e.match(/received (\w+)(?:\s|$)/)?.[1]}function u(e){switch(e.code){case`invalid_type`:{let t=e;return l(t.message)===`undefined`?`Required field is missing`:t.message}case`invalid_value`:return`Invalid value — must be one of: ${e.values.join(`, `)}`;case`too_small`:{let t=e;return`Value too small — minimum is ${String(t.minimum)}${t.inclusive?` (inclusive)`:` (exclusive)`}`}case`too_big`:{let t=e;return`Value too large — maximum is ${String(t.maximum)}${t.inclusive?` (inclusive)`:` (exclusive)`}`}case`unrecognized_keys`:return`Unrecognized keys: ${e.keys.join(`, `)}`;default:return e.message}}function d(e,t,n){let r=`--${t}`;switch(e.code){case`invalid_type`:{let t=e,i=l(t.message);return i===`undefined`?`Provide: ${r} <${n?c(n):`value`}>`:i===`string`&&(t.expected===`record`||t.expected===`array`||t.expected===`object`)?`Received a JSON string instead of ${t.expected}.\n → The coercion layer should handle this automatically.\n → CLI usage: ${r} '<json ${t.expected}>'`:void 0}case`invalid_value`:{let t=e.values[0];return`Use: ${r} ${String(t)}`}default:return}}function f(e,t){if(e.length!==0)return t.shape[e[0]]}function p(e,t){let{schemaName:n,schema:r}=t??{},i=new Map;for(let t of e.issues){let e=t.path.length>0?t.path.map(String).join(`.`):`(root)`,n=i.get(e)??[];n.push(t),i.set(e,n)}let a=[n?`Validation failed for "${n}":`:`Validation failed:`];for(let[e,t]of i){a.push(``);let n=r?f(e.split(`.`),r):void 0,i=n?s(n):t.some(e=>{if(e.code!==`invalid_type`)return!1;let t=e.message;return l(t)===`undefined`}),o=n?c(n):``,p=`(${i?`required`:`optional`})${o?` — ${o}`:``}`;a.push(` • ${e} ${p}`);for(let r of t){a.push(` ✗ ${u(r)}`);let t=d(r,e,n);t&&a.push(` → ${t}`)}}return a.join(`
2
+ `)}function m(e){return e._def.type??``}function h(e){return e._def.innerType}function g(e){let t=m(e);if(t===`optional`||t===`nullable`||t===`default`){let t=h(e);return t?g(t):e}return e}function _(e){let t=m(e);return t!==`optional`&&t!==`default`}function v(e){if(m(e)===`default`)return e._def.defaultValue}function y(e){return e.description??``}function b(e){let t=g(e);switch(m(t)){case`boolean`:return`boolean`;case`number`:return`number`;case`object`:case`record`:case`array`:return`json`;case`union`:return(t._def.options??[]).some(e=>{let t=m(g(e));return t===`object`||t===`array`||t===`record`})?`json`:`string`;default:return`string`}}function x(e){let t=g(e);if(m(t)===`enum`)return t.options}function S(e,t){if(t&&t.length>0)return`<${t.join(`|`)}>`;switch(e){case`boolean`:return``;case`number`:return`<number>`;case`json`:return`<json>`;default:return`<string>`}}function C(e,t){let n=b(t),r=x(t),i=v(t),a=y(t);return{flag:`--${e}`,type:n,required:_(t),description:a,default:i,choices:r,typeLabel:c(t)}}function w(e,t){return e.length>=t?`${e} `:e.padEnd(t)}function T(e){let t=S(e.type,e.choices),n=t?`${e.flag} ${t}`:e.flag,r=e.type===`json`?` — ${e.typeLabel}`:``,i=e.default===void 0?``:` [default: ${JSON.stringify(e.default)}]`,a=`${e.description}${r}${i}`.trim();return` ${w(n,36)}${a}`}function E(e,t){let n=[],r=t.command??`<tool>`;n.push(`Usage: ${r} [options]`),t.description&&(n.push(``),n.push(t.description));let i=e.filter(e=>e.required),a=e.filter(e=>!e.required);if(i.length>0){n.push(``),n.push(`Required:`);for(let e of i)n.push(T(e))}if(a.length>0){n.push(``),n.push(`Optional:`);for(let e of a)n.push(T(e))}return n.join(`
3
+ `)}function D(e,t){let n=Object.entries(e.shape).map(([e,t])=>C(e,t));return{args:n,help:E(n,t??{})}}function O(e){return(e.startsWith(`--`)?e.slice(2):e).replace(/-([a-z])/gi,(e,t)=>t.toUpperCase())}function k(e,t){let{args:n}=D(t),r=new Map(n.map(e=>[O(e.flag),e])),i=new Map(n.map(e=>[e.flag,e])),a={},o=0;for(;o<e.length;){let t=e[o];if(!t.startsWith(`--`)){o++;continue}if(t.startsWith(`--no-`)){let e=O(t.slice(5));a[e]=!1,o++;continue}let n=t.indexOf(`=`),s,c;n===-1?(s=t,c=void 0):(s=t.slice(0,n),c=t.slice(n+1));let l=O(s),u=r.get(l)??i.get(s);if(u?.type===`boolean`){a[l]=!0,o++;continue}let d;if(c!==void 0)d=c,o++;else if(o+1<e.length&&!e[o+1].startsWith(`--`))d=e[o+1],o+=2;else{a[l]=!0,o++;continue}if(u?.type===`json`)try{a[l]=JSON.parse(d)}catch{a[l]=d}else if(u?.type===`number`){let e=Number.parseFloat(d);a[l]=Number.isNaN(e)?d:e}else a[l]=d}return a}function A(t){if(!t||typeof t!=`object`||Array.isArray(t))return e.unknown();let n=t,r=n.anyOf??n.oneOf;if(Array.isArray(r)&&r.length>0){let t=r.map(A);return t.length===1?t[0]:e.union([t[0],t[1],...t.slice(2)])}if(Array.isArray(n.enum)&&n.enum.every(e=>typeof e==`string`)){let[t,r,...i]=n.enum;return t===void 0?e.unknown():r===void 0?e.literal(t):e.enum([t,r,...i])}let i=n.type;if(Array.isArray(i)){let t=i.filter(e=>e!==`null`),r=i.includes(`null`);if(t.length===0)return r?e.null():e.unknown();let a=t.length===1?A({...n,type:t[0]}):e.union(t.map(e=>A({...n,type:e})));return r?e.union([a,e.null()]):a}if(i===`string`)return e.string();if(i===`number`||i===`integer`)return e.number();if(i===`boolean`)return e.boolean();if(i===`null`)return e.null();if(i===`array`){let t=n.items?A(n.items):e.unknown();return e.array(t)}return i===`object`?n.properties&&typeof n.properties==`object`&&!Array.isArray(n.properties)?j(n):e.record(e.string(),e.unknown()):e.unknown()}function j(t){let n=t.properties,r=new Set(Array.isArray(t.required)?t.required:[]);if(!n)return e.object({});let i={};for(let[e,t]of Object.entries(n)){let n=A(t);i[e]=r.has(e)?n:n.optional()}return e.object(i)}export{k as cliArgsToObject,i as coerceArgs,c as describeType,p as formatZodError,j as jsonSchemaToZod,D as zodToCliArgs};
4
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["defType","defType","defInnerType","isRequired","lines: string[]","lines: string[]","result: Record<string, unknown>","key","flagToken: string","inlineValue: string | undefined","rawValue: string | undefined","shape: Record<string, z.ZodTypeAny>"],"sources":["../src/utils/coerceArgs.ts","../src/utils/formatZodError.ts","../src/utils/zodToCliArgs.ts","../src/utils/cliArgsToObject.ts","../src/utils/jsonSchemaToZod.ts"],"sourcesContent":["import { z } from 'zod';\n\n// ---------------------------------------------------------------------------\n// Internal helpers — Zod v4 compatible\n// ---------------------------------------------------------------------------\n\n// Zod v4 schema shapes expose $ZodType internally; use a structural interface\n// to avoid the public ZodType vs $ZodType mismatch.\ninterface ZodLike {\n _def: { type?: string; innerType?: ZodLike; options?: ZodLike[] };\n}\n\nfunction defType(schema: ZodLike): string {\n return schema._def.type ?? '';\n}\n\nfunction unwrapZodLike(schema: ZodLike): ZodLike {\n const t = defType(schema);\n if (t === 'optional' || t === 'nullable' || t === 'default') {\n const inner = schema._def.innerType;\n return inner ? unwrapZodLike(inner) : schema;\n }\n return schema;\n}\n\nfunction isNonPrimitive(schema: ZodLike): boolean {\n const core = unwrapZodLike(schema);\n const t = defType(core);\n if (t === 'object' || t === 'array' || t === 'record') return true;\n if (t === 'union') {\n return (core._def.options ?? []).some(isNonPrimitive);\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Walks a ZodObject's shape and, for any field that expects a non-primitive\n * type (object, array, record, or union containing one), attempts to\n * JSON.parse string values. Leaves the value unchanged if:\n * - it is not a string\n * - the schema expects a primitive\n * - the string is not valid JSON\n *\n * This handles the common Claude Code behaviour of stringifying nested args\n * (e.g. env: '{\"KEY\":\"val\"}' instead of env: { KEY: 'val' }).\n */\nexport function coerceArgs(args: Record<string, unknown>, schema: z.ZodObject<z.ZodRawShape>): Record<string, unknown> {\n const result = { ...args };\n\n for (const [key, rawSchema] of Object.entries(schema.shape)) {\n const value = result[key];\n if (typeof value !== 'string') continue;\n if (!isNonPrimitive(rawSchema as unknown as ZodLike)) continue;\n\n try {\n result[key] = JSON.parse(value);\n } catch {\n // keep as string — not valid JSON\n }\n }\n\n return result;\n}\n","import { z } from 'zod';\n\n// ---------------------------------------------------------------------------\n// Internal schema introspection — Zod v4 compatible\n// ---------------------------------------------------------------------------\n\n// Structural interface compatible with both $ZodType (internal) and ZodType (public)\ninterface ZodLike {\n _def: {\n type?: string;\n innerType?: ZodLike;\n element?: ZodLike;\n valueType?: ZodLike;\n options?: readonly ZodLike[];\n value?: unknown;\n };\n description?: string;\n}\n\nfunction defType(schema: ZodLike): string {\n return schema._def.type ?? '';\n}\n\nfunction defInnerType(schema: ZodLike): ZodLike | undefined {\n return schema._def.innerType;\n}\n\nfunction isRequired(schema: ZodLike): boolean {\n const t = defType(schema);\n return t !== 'optional' && t !== 'default';\n}\n\n/**\n * Produces a concise human-readable type label for a Zod schema.\n * Examples: 'string', 'string[]', 'Record<string, string>', 'enum [a, b]'\n */\nexport function describeType(schema: ZodLike): string {\n const t = defType(schema);\n switch (t) {\n case 'string':\n return 'string';\n case 'number':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'bigint':\n return 'bigint';\n case 'null':\n return 'null';\n case 'undefined':\n return 'undefined';\n case 'any':\n return 'any';\n case 'unknown':\n return 'unknown';\n case 'literal':\n return JSON.stringify(schema._def.value);\n case 'enum': {\n // ZodEnum in v4 exposes .options as a getter\n const opts = (schema as unknown as { options: string[] }).options ?? [];\n return `enum [${opts.join(', ')}]`;\n }\n case 'array': {\n const el = schema._def.element;\n return el ? `${describeType(el)}[]` : 'unknown[]';\n }\n case 'record': {\n const valType = schema._def.valueType;\n return valType ? `Record<string, ${describeType(valType)}>` : 'Record<string, unknown>';\n }\n case 'object':\n return 'object';\n case 'optional':\n case 'nullable':\n case 'default': {\n const inner = defInnerType(schema);\n return inner ? describeType(inner) : 'unknown';\n }\n case 'union': {\n const opts = schema._def.options ?? [];\n return opts.map(describeType).join(' | ');\n }\n default:\n return 'unknown';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Issue formatting — Zod v4 issue shapes\n// ---------------------------------------------------------------------------\n\n// Zod v4 uses 'invalid_value' (not 'invalid_enum_value') for enum violations.\n// Use string cast on issue.code to avoid ZodIssueCode constraint errors.\n\ninterface InvalidTypeIssueV4 {\n code: string;\n expected: string;\n message: string;\n path: (string | number)[];\n}\n\ninterface InvalidValueIssueV4 {\n code: string;\n values: (string | number)[];\n message: string;\n path: (string | number)[];\n}\n\ninterface TooSmallIssueV4 {\n code: string;\n minimum: number | bigint;\n inclusive: boolean;\n message: string;\n path: (string | number)[];\n}\n\ninterface TooBigIssueV4 {\n code: string;\n maximum: number | bigint;\n inclusive: boolean;\n message: string;\n path: (string | number)[];\n}\n\ninterface UnrecognizedKeysIssueV4 {\n code: string;\n keys: string[];\n message: string;\n path: (string | number)[];\n}\n\nfunction extractReceived(message: string): string | undefined {\n return message.match(/received (\\w+)(?:\\s|$)/)?.[1];\n}\n\nfunction formatIssueMessage(issue: z.ZodIssue): string {\n const code = issue.code as string;\n switch (code) {\n case 'invalid_type': {\n const i = issue as unknown as InvalidTypeIssueV4;\n const received = extractReceived(i.message);\n if (received === 'undefined') return 'Required field is missing';\n return i.message;\n }\n // Zod v4 uses 'invalid_value' for enum violations\n case 'invalid_value': {\n const i = issue as unknown as InvalidValueIssueV4;\n return `Invalid value — must be one of: ${i.values.join(', ')}`;\n }\n case 'too_small': {\n const i = issue as unknown as TooSmallIssueV4;\n return `Value too small — minimum is ${String(i.minimum)}${i.inclusive ? ' (inclusive)' : ' (exclusive)'}`;\n }\n case 'too_big': {\n const i = issue as unknown as TooBigIssueV4;\n return `Value too large — maximum is ${String(i.maximum)}${i.inclusive ? ' (inclusive)' : ' (exclusive)'}`;\n }\n case 'unrecognized_keys': {\n const i = issue as unknown as UnrecognizedKeysIssueV4;\n return `Unrecognized keys: ${i.keys.join(', ')}`;\n }\n default:\n return issue.message;\n }\n}\n\nfunction getActionableHint(issue: z.ZodIssue, fieldPath: string, fieldSchema: ZodLike | undefined): string | undefined {\n const flag = `--${fieldPath}`;\n const code = issue.code as string;\n\n switch (code) {\n case 'invalid_type': {\n const i = issue as unknown as InvalidTypeIssueV4;\n const received = extractReceived(i.message);\n\n if (received === 'undefined') {\n const typeLabel = fieldSchema ? describeType(fieldSchema) : 'value';\n return `Provide: ${flag} <${typeLabel}>`;\n }\n\n if (received === 'string' && (i.expected === 'record' || i.expected === 'array' || i.expected === 'object')) {\n return `Received a JSON string instead of ${i.expected}.\\n → The coercion layer should handle this automatically.\\n → CLI usage: ${flag} '<json ${i.expected}>'`;\n }\n\n return undefined;\n }\n\n case 'invalid_value': {\n const i = issue as unknown as InvalidValueIssueV4;\n const example = i.values[0];\n return `Use: ${flag} ${String(example)}`;\n }\n\n default:\n return undefined;\n }\n}\n\nfunction getFieldSchema(pathSegments: string[], schema: z.ZodObject<z.ZodRawShape>): ZodLike | undefined {\n if (pathSegments.length === 0) return undefined;\n return schema.shape[pathSegments[0]] as unknown as ZodLike | undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Converts a ZodError into a multi-line string optimized for AI agents.\n *\n * Each field with errors shows:\n * - field name, whether it is required/optional, and its expected type\n * - a concise description of what went wrong\n * - a concrete actionable hint (e.g. CLI flag usage)\n *\n * Detecting stringified objects: when the error says \"expected record/array,\n * received string\", it calls out the common Claude Code serialisation issue\n * and explains that the coercion layer should handle it automatically.\n *\n * @example\n * try {\n * schema.parse(args);\n * } catch (err) {\n * if (err instanceof z.ZodError) {\n * console.error(formatZodError(err, { schemaName: 'run_spec', schema }));\n * }\n * }\n */\nexport function formatZodError(\n error: z.ZodError,\n options?: { schemaName?: string; schema?: z.ZodObject<z.ZodRawShape> },\n): string {\n const { schemaName, schema } = options ?? {};\n\n // Group issues by dotted path\n const byPath = new Map<string, z.ZodIssue[]>();\n for (const issue of error.issues) {\n const path = issue.path.length > 0 ? issue.path.map(String).join('.') : '(root)';\n const existing = byPath.get(path) ?? [];\n existing.push(issue);\n byPath.set(path, existing);\n }\n\n const header = schemaName ? `Validation failed for \"${schemaName}\":` : 'Validation failed:';\n const lines: string[] = [header];\n\n for (const [path, issues] of byPath) {\n lines.push('');\n\n const fieldSchema = schema ? getFieldSchema(path.split('.'), schema) : undefined;\n const required = fieldSchema\n ? isRequired(fieldSchema)\n : issues.some((i) => {\n if ((i.code as string) !== 'invalid_type') return false;\n const msg = (i as unknown as { message: string }).message;\n return extractReceived(msg) === 'undefined';\n });\n\n const typeDesc = fieldSchema ? describeType(fieldSchema) : '';\n const meta = `(${required ? 'required' : 'optional'})${typeDesc ? ` — ${typeDesc}` : ''}`;\n\n lines.push(` • ${path} ${meta}`);\n\n for (const issue of issues) {\n lines.push(` ✗ ${formatIssueMessage(issue)}`);\n const hint = getActionableHint(issue, path, fieldSchema);\n if (hint) {\n lines.push(` → ${hint}`);\n }\n }\n }\n\n return lines.join('\\n');\n}\n","import { z } from 'zod';\nimport type { CliArgDefinition, CliArgType, CliArgsResult } from '../types/index.js';\nimport { describeType } from './formatZodError.js';\n\n// ---------------------------------------------------------------------------\n// Internal helpers — Zod v4 compatible\n// ---------------------------------------------------------------------------\n\n// Structural interface compatible with both $ZodType (internal) and ZodType (public)\ninterface ZodLike {\n _def: { type?: string; innerType?: ZodLike; defaultValue?: unknown; options?: readonly ZodLike[] };\n description?: string;\n}\n\nfunction defType(schema: ZodLike): string {\n return schema._def.type ?? '';\n}\n\nfunction defInnerType(schema: ZodLike): ZodLike | undefined {\n return schema._def.innerType;\n}\n\nfunction unwrapSchema(schema: ZodLike): ZodLike {\n const t = defType(schema);\n if (t === 'optional' || t === 'nullable' || t === 'default') {\n const inner = defInnerType(schema);\n return inner ? unwrapSchema(inner) : schema;\n }\n return schema;\n}\n\nfunction isRequired(schema: ZodLike): boolean {\n const t = defType(schema);\n return t !== 'optional' && t !== 'default';\n}\n\nfunction getDefault(schema: ZodLike): unknown {\n if (defType(schema) === 'default') {\n return schema._def.defaultValue;\n }\n return undefined;\n}\n\nfunction getDescription(schema: ZodLike): string {\n return schema.description ?? '';\n}\n\n/**\n * Maps a Zod schema field to a CliArgType used for help text and parsing.\n */\nfunction resolveCliType(schema: ZodLike): CliArgType {\n const core = unwrapSchema(schema);\n const t = defType(core);\n\n switch (t) {\n case 'boolean':\n return 'boolean';\n case 'number':\n return 'number';\n case 'object':\n case 'record':\n case 'array':\n return 'json';\n case 'union': {\n const opts: readonly ZodLike[] = core._def.options ?? [];\n const hasNonPrimitive = opts.some((o) => {\n const ot = defType(unwrapSchema(o));\n return ot === 'object' || ot === 'array' || ot === 'record';\n });\n return hasNonPrimitive ? 'json' : 'string';\n }\n default:\n return 'string';\n }\n}\n\n/**\n * Returns enum choices if the (unwrapped) schema is a ZodEnum.\n */\nfunction getChoices(schema: ZodLike): string[] | undefined {\n const core = unwrapSchema(schema);\n if (defType(core) === 'enum') {\n return (core as unknown as { options: string[] }).options;\n }\n return undefined;\n}\n\n/**\n * Builds the value placeholder shown in help text, e.g. '<string>', '<json>',\n * '<playwright|extension>'.\n */\nfunction buildValuePlaceholder(argType: CliArgType, choices?: string[]): string {\n if (choices && choices.length > 0) return `<${choices.join('|')}>`;\n switch (argType) {\n case 'boolean':\n return '';\n case 'number':\n return '<number>';\n case 'json':\n return '<json>';\n default:\n return '<string>';\n }\n}\n\n/**\n * Converts a single schema field to a CliArgDefinition.\n */\nfunction fieldToCliArg(key: string, schema: ZodLike): CliArgDefinition {\n const argType = resolveCliType(schema);\n const choices = getChoices(schema);\n const defaultVal = getDefault(schema);\n const desc = getDescription(schema);\n\n return {\n flag: `--${key}`,\n type: argType,\n required: isRequired(schema),\n description: desc,\n default: defaultVal,\n choices,\n typeLabel: describeType(schema),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Help text formatting\n// ---------------------------------------------------------------------------\n\nconst COL_WIDTH = 36;\n\nfunction padEnd(str: string, width: number): string {\n return str.length >= width ? `${str} ` : str.padEnd(width);\n}\n\nfunction renderArg(arg: CliArgDefinition): string {\n const placeholder = buildValuePlaceholder(arg.type, arg.choices);\n const flagPart = placeholder ? `${arg.flag} ${placeholder}` : arg.flag;\n\n const typeAnnotation = arg.type === 'json' ? ` — ${arg.typeLabel}` : '';\n const defaultAnnotation = arg.default !== undefined ? ` [default: ${JSON.stringify(arg.default)}]` : '';\n const description = `${arg.description}${typeAnnotation}${defaultAnnotation}`.trim();\n\n return ` ${padEnd(flagPart, COL_WIDTH)}${description}`;\n}\n\nfunction formatHelp(args: CliArgDefinition[], options: { command?: string; description?: string }): string {\n const lines: string[] = [];\n\n const commandName = options.command ?? '<tool>';\n lines.push(`Usage: ${commandName} [options]`);\n\n if (options.description) {\n lines.push('');\n lines.push(options.description);\n }\n\n const required = args.filter((a) => a.required);\n const optional = args.filter((a) => !a.required);\n\n if (required.length > 0) {\n lines.push('');\n lines.push('Required:');\n for (const arg of required) {\n lines.push(renderArg(arg));\n }\n }\n\n if (optional.length > 0) {\n lines.push('');\n lines.push('Optional:');\n for (const arg of optional) {\n lines.push(renderArg(arg));\n }\n }\n\n return lines.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Converts a ZodObject schema to:\n * - `args`: structured CliArgDefinition[] for programmatic use (e.g. parsing)\n * - `help`: formatted help string equivalent to `--help` output\n *\n * Enables AI agents to inspect a tool's expected arguments as CLI flags,\n * then reconstruct a valid call using {@link cliArgsToObject}.\n *\n * @example\n * const { help } = zodToCliArgs(RunSpecToolInputSchema, { command: 'run_spec' });\n * console.log(help);\n * // Usage: run_spec [options]\n * //\n * // Required:\n * // --specPath <string> Absolute path to the spec file\n * //\n * // Optional:\n * // --headless Run in headless mode [default: true]\n * // --env <json> Environment variables — Record<string, string>\n */\nexport function zodToCliArgs(\n schema: z.ZodObject<z.ZodRawShape>,\n options?: { command?: string; description?: string },\n): CliArgsResult {\n const args = Object.entries(schema.shape).map(([key, fieldSchema]) =>\n fieldToCliArg(key, fieldSchema as unknown as ZodLike),\n );\n\n const help = formatHelp(args, options ?? {});\n\n return { args, help };\n}\n","import { z } from 'zod';\nimport { zodToCliArgs } from './zodToCliArgs.js';\n\n// ---------------------------------------------------------------------------\n// Key normalisation\n// ---------------------------------------------------------------------------\n\n/**\n * Converts a CLI flag name (without --) to a camelCase object key.\n * Supports both kebab-case and camelCase input:\n * 'spec-path' → 'specPath'\n * 'specPath' → 'specPath'\n * 'base-url' → 'baseURL' (only uppercases the first letter after -)\n */\nfunction flagToKey(flag: string): string {\n // strip leading -- if present\n const raw = flag.startsWith('--') ? flag.slice(2) : flag;\n // kebab-case → camelCase\n return raw.replace(/-([a-z])/gi, (_, c: string) => c.toUpperCase());\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Parses a CLI argv array (e.g. process.argv.slice(2)) into a\n * Record<string, unknown> that can be validated by a Zod schema.\n *\n * Uses the schema to determine which flags are booleans (no value expected)\n * and which expect a JSON value (auto-parsed). The result can be passed\n * directly to {@link coerceArgs} or schema.parse().\n *\n * Parsing rules:\n * --flag (boolean in schema) → { flag: true }\n * --no-flag → { flag: false }\n * --key value (json in schema) → { key: JSON.parse(value) }\n * --key value (number in schema) → { key: parseFloat(value) }\n * --key value (string/default) → { key: value }\n * Kebab-case flags are converted to camelCase automatically.\n *\n * @example\n * const obj = cliArgsToObject(\n * ['--specPath', '/tests/foo.spec.ts', '--headless', '--env', '{\"KEY\":\"val\"}'],\n * RunSpecToolInputSchema,\n * );\n * // { specPath: '/tests/foo.spec.ts', headless: true, env: { KEY: 'val' } }\n */\nexport function cliArgsToObject(argv: string[], schema: z.ZodObject<z.ZodRawShape>): Record<string, unknown> {\n const { args: argDefs } = zodToCliArgs(schema);\n\n // Build lookup maps: both camelCase and kebab forms → CliArgDefinition\n const byKey = new Map(argDefs.map((d) => [flagToKey(d.flag), d]));\n // Also support kebab-case lookups (the flag already starts with --)\n const byFlag = new Map(argDefs.map((d) => [d.flag, d]));\n\n const result: Record<string, unknown> = {};\n\n let i = 0;\n while (i < argv.length) {\n const token = argv[i];\n\n if (!token.startsWith('--')) {\n i++;\n continue;\n }\n\n // Handle --no-<flag> negation\n if (token.startsWith('--no-')) {\n const key = flagToKey(token.slice(5)); // strip --no-\n result[key] = false;\n i++;\n continue;\n }\n\n // Support --key=value syntax\n const eqIdx = token.indexOf('=');\n let flagToken: string;\n let inlineValue: string | undefined;\n\n if (eqIdx !== -1) {\n flagToken = token.slice(0, eqIdx);\n inlineValue = token.slice(eqIdx + 1);\n } else {\n flagToken = token;\n inlineValue = undefined;\n }\n\n const key = flagToKey(flagToken);\n const argDef = byKey.get(key) ?? byFlag.get(flagToken);\n\n // Boolean flags: presence alone means true\n if (argDef?.type === 'boolean') {\n result[key] = true;\n i++;\n continue;\n }\n\n // Determine the value: inline (--key=val) or next token\n let rawValue: string | undefined;\n if (inlineValue !== undefined) {\n rawValue = inlineValue;\n i++;\n } else if (i + 1 < argv.length && !argv[i + 1].startsWith('--')) {\n rawValue = argv[i + 1];\n i += 2;\n } else {\n // No value token following — treat as boolean true\n result[key] = true;\n i++;\n continue;\n }\n\n // Parse value based on schema type\n if (argDef?.type === 'json') {\n try {\n result[key] = JSON.parse(rawValue);\n } catch {\n result[key] = rawValue;\n }\n } else if (argDef?.type === 'number') {\n const parsed = Number.parseFloat(rawValue);\n result[key] = Number.isNaN(parsed) ? rawValue : parsed;\n } else {\n result[key] = rawValue;\n }\n }\n\n return result;\n}\n","import { z } from 'zod';\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\ntype JsonSchemaNode = Record<string, unknown>;\n\n/**\n * Convert a single JSON Schema property node to a Zod type.\n * Handles: string, number, integer, boolean, null, array, object,\n * anyOf/oneOf, enum, and array-of-types (e.g. [\"string\",\"null\"]).\n */\nfunction propertyToZod(node: unknown): z.ZodTypeAny {\n if (!node || typeof node !== 'object' || Array.isArray(node)) return z.unknown();\n const n = node as JsonSchemaNode;\n\n // anyOf / oneOf → union\n const variants = (n.anyOf ?? n.oneOf) as unknown[] | undefined;\n if (Array.isArray(variants) && variants.length > 0) {\n const members = variants.map(propertyToZod);\n if (members.length === 1) return members[0];\n return z.union([members[0], members[1], ...members.slice(2)] as [z.ZodTypeAny, z.ZodTypeAny, ...z.ZodTypeAny[]]);\n }\n\n // enum\n if (Array.isArray(n.enum) && n.enum.every((v) => typeof v === 'string')) {\n const [first, second, ...rest] = n.enum as string[];\n if (first === undefined) return z.unknown();\n if (second === undefined) return z.literal(first);\n return z.enum([first, second, ...rest]);\n }\n\n const type = n.type;\n\n // Array-of-types: [\"string\", \"null\"] → optional string\n if (Array.isArray(type)) {\n const nonNull = type.filter((t) => t !== 'null') as string[];\n const nullable = type.includes('null');\n if (nonNull.length === 0) return nullable ? z.null() : z.unknown();\n const inner =\n nonNull.length === 1\n ? propertyToZod({ ...n, type: nonNull[0] })\n : z.union(\n nonNull.map((t) => propertyToZod({ ...n, type: t })) as [z.ZodTypeAny, z.ZodTypeAny, ...z.ZodTypeAny[]],\n );\n return nullable ? z.union([inner, z.null()]) : inner;\n }\n\n if (type === 'string') return z.string();\n if (type === 'number' || type === 'integer') return z.number();\n if (type === 'boolean') return z.boolean();\n if (type === 'null') return z.null();\n\n if (type === 'array') {\n const items = n.items ? propertyToZod(n.items) : z.unknown();\n return z.array(items);\n }\n\n if (type === 'object') {\n if (n.properties && typeof n.properties === 'object' && !Array.isArray(n.properties)) {\n return jsonSchemaToZod(n);\n }\n return z.record(z.string(), z.unknown());\n }\n\n return z.unknown();\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Convert a JSON Schema object definition to a Zod object schema.\n *\n * Handles `properties`, `required`, `anyOf`/`oneOf`, `enum`, and the\n * common scalar types. Fields not listed in `required` are made optional.\n * Unknown/unsupported nodes map to `z.unknown()`.\n *\n * This is intentionally non-exhaustive: the goal is accurate type\n * classification for coercion (primitive vs non-primitive), not strict\n * schema validation.\n *\n * @example\n * const schema = jsonSchemaToZod({\n * type: 'object',\n * properties: {\n * env: { type: 'object' },\n * headless: { type: 'boolean' },\n * },\n * required: ['env'],\n * });\n * // schema.shape.env → ZodRecord (non-primitive → will be JSON.parsed if string)\n * // schema.shape.headless → ZodOptional<ZodBoolean>\n */\nexport function jsonSchemaToZod(schema: Record<string, unknown>): z.ZodObject<z.ZodRawShape> {\n const properties = schema.properties as Record<string, unknown> | undefined;\n const required = new Set<string>(Array.isArray(schema.required) ? (schema.required as string[]) : []);\n\n if (!properties) return z.object({});\n\n const shape: Record<string, z.ZodTypeAny> = {};\n for (const [key, prop] of Object.entries(properties)) {\n const zodType = propertyToZod(prop);\n shape[key] = required.has(key) ? zodType : zodType.optional();\n }\n\n return z.object(shape);\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@agimon-ai/foundation-validator",
3
+ "version": "0.2.0",
4
+ "description": "Zod-based validation utilities: schema coercion, AI-readable error formatting, and CLI arg conversion",
5
+ "main": "./dist/index.cjs",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.mts",
8
+ "sideEffects": false,
9
+ "publishConfig": {
10
+ "access": "public"
11
+ },
12
+ "dependencies": {
13
+ "zod": "4.3.6"
14
+ },
15
+ "devDependencies": {
16
+ "@types/node": "^22.0.0",
17
+ "tsdown": "0.16.1",
18
+ "typescript": "5.9.3",
19
+ "vitest": "4.0.18"
20
+ },
21
+ "author": "Vuong Ngo",
22
+ "license": "BUSL-1.1",
23
+ "type": "module",
24
+ "exports": {
25
+ ".": {
26
+ "types": "./dist/index.d.mts",
27
+ "import": "./dist/index.mjs",
28
+ "require": "./dist/index.cjs"
29
+ },
30
+ "./*": "./*"
31
+ },
32
+ "files": [
33
+ "dist",
34
+ "README.md"
35
+ ],
36
+ "scripts": {
37
+ "build": "tsdown",
38
+ "test": "vitest run --coverage.enabled=false",
39
+ "lint": "eslint src",
40
+ "fixcode": "pnpm exec biome check --write",
41
+ "typecheck": "tsc --noEmit"
42
+ }
43
+ }