@@ -4,18 +4,20 @@ import { defineSemanticCommand, type JsonSchema } from './semantic-contract.ts';
44import { prepareSemanticBatchStep , type SemanticDaemonCommand } from './semantic-grammar.ts' ;
55import {
66 assertAllowedKeys ,
7- commandInputSchema ,
87 commonToClientOptions ,
9- optionalEnum ,
10- optionalInteger ,
11- optionalString ,
12- readCommonInput ,
13- readInputRecord ,
8+ customField ,
9+ enumField ,
10+ fieldsInputSchema ,
11+ integerField ,
12+ readFieldInput ,
1413 requiredEnum ,
15- type CommonCommandInput ,
14+ requiredField ,
15+ stringField ,
16+ type InferCommandInput ,
17+ type SemanticFieldMap ,
1618} from './semantic-common.ts' ;
1719
18- type BatchInput = CommonCommandInput & {
20+ type BatchInput = InferCommandInput < SemanticFieldMap > & {
1921 steps : BatchStep [ ] ;
2022 onError ?: 'stop' ;
2123 maxSteps ?: number ;
@@ -25,32 +27,37 @@ type BatchInput = CommonCommandInput & {
2527export function createBatchSemanticCommand < const TCommand extends SemanticDaemonCommand > (
2628 nestedCommands : readonly TCommand [ ] ,
2729) {
30+ const fields = batchFields ( nestedCommands ) ;
2831 return defineSemanticCommand ( {
2932 name : 'batch' ,
3033 description : 'Run multiple structured command steps in one daemon request.' ,
31- inputSchema : commandInputSchema (
32- {
33- steps : {
34+ inputSchema : fieldsInputSchema ( fields ) ,
35+ outputSchema : batchResultSchema ( ) ,
36+ readInput : ( input ) => readBatchInput ( input , fields ) ,
37+ run : ( client , input ) => client . batch . run ( toBatchOptions ( input ) ) ,
38+ } ) ;
39+ }
40+
41+ function batchFields ( nestedCommands : readonly SemanticDaemonCommand [ ] ) {
42+ return {
43+ steps : requiredField (
44+ customField < BatchStep [ ] > (
45+ {
3446 type : 'array' ,
3547 description :
3648 'Structured batch steps. CLI JSON parsing belongs to the CLI normalizer; MCP passes this array directly.' ,
3749 items : batchStepSchema ( nestedCommands ) ,
3850 } ,
39- onError : { type : 'string' , enum : [ 'stop' ] , description : 'Batch failure policy.' } ,
40- maxSteps : {
41- type : 'integer' ,
42- minimum : 1 ,
43- maximum : 1000 ,
44- description : 'Maximum number of steps accepted for this batch.' ,
45- } ,
46- out : { type : 'string' , description : 'Optional output path for command artifacts.' } ,
47- } ,
48- [ 'steps' ] ,
51+ ( record , key ) => readBatchSteps ( record [ key ] , nestedCommands ) ,
52+ ) ,
4953 ) ,
50- outputSchema : batchResultSchema ( ) ,
51- readInput : ( input ) => readBatchInput ( input , nestedCommands ) ,
52- run : ( client , input ) => client . batch . run ( toBatchOptions ( input ) ) ,
53- } ) ;
54+ onError : enumField ( [ 'stop' ] as const , 'Batch failure policy.' ) ,
55+ maxSteps : integerField ( 'Maximum number of steps accepted for this batch.' , {
56+ min : 1 ,
57+ max : 1000 ,
58+ } ) ,
59+ out : stringField ( 'Optional output path for command artifacts.' ) ,
60+ } ;
5461}
5562
5663function batchStepSchema ( nestedCommands : readonly SemanticDaemonCommand [ ] ) : JsonSchema {
@@ -90,27 +97,20 @@ function batchResultSchema(): JsonSchema {
9097 } ;
9198}
9299
93- function readBatchInput (
94- input : unknown ,
95- nestedCommands : readonly SemanticDaemonCommand [ ] ,
96- ) : BatchInput {
97- const record = readInputRecord ( input ) ;
98- const maxSteps = optionalInteger ( record , 'maxSteps' , { min : 1 , max : 1000 } ) ;
100+ function readBatchInput ( input : unknown , fields : ReturnType < typeof batchFields > ) : BatchInput {
101+ const parsed = readFieldInput ( input , fields ) ;
99102 const normalized = validateAndNormalizeBatchSteps (
100- readBatchSteps ( record . steps , nestedCommands ) ,
101- maxSteps ?? DEFAULT_BATCH_MAX_STEPS ,
103+ parsed . steps ,
104+ parsed . maxSteps ?? DEFAULT_BATCH_MAX_STEPS ,
102105 ) ;
103106 return {
104- ...readCommonInput ( record ) ,
107+ ...parsed ,
105108 steps : normalized . map ( ( { command, positionals, flags, runtime } ) => ( {
106109 command,
107110 positionals,
108111 flags,
109112 runtime,
110113 } ) ) ,
111- onError : optionalEnum ( record , 'onError' , [ 'stop' ] as const ) ,
112- maxSteps,
113- out : optionalString ( record , 'out' ) ,
114114 } ;
115115}
116116
0 commit comments