File size: 2,208 Bytes
a0a9254 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | """Strict browser decision request contract; values and UI mechanics stay in Node."""
def validate_request(payload):
if not isinstance(payload,dict) or set(payload)!={'states'}:
raise ValueError('Expected {"states": [...]}')
states=payload['states']
if not isinstance(states,list) or not 1<=len(states)<=32:
raise ValueError('Expected 1–32 states')
seen=set();question_count=path_count=0
for state in states:
if not isinstance(state,dict) or set(state)!={'id','state','questions'}:
raise ValueError('Each state requires id, state, questions')
sid=state['id']
if not isinstance(sid,str) or not sid.strip() or sid in seen:
raise ValueError('State IDs must be unique nonempty strings')
seen.add(sid)
if not isinstance(state['state'],(str,dict,list)) or not state['state']:
raise ValueError('State must be nonempty text, object or list')
questions=state['questions']
if not isinstance(questions,dict) or not questions:
raise ValueError('Questions must be a nonempty object')
for qid,q in questions.items():
if not isinstance(qid,str) or not qid.strip() or not isinstance(q,dict):
raise ValueError('Invalid question')
if set(q)!={'type','instructions','criteria'} or q['type']!='choice':
raise ValueError('Browser API supports choice questions only')
if not isinstance(q['instructions'],str) or not q['instructions'].strip():
raise ValueError('Instructions must be nonempty text')
criteria=q['criteria']
if not isinstance(criteria,dict) or not 2<=len(criteria)<=255:
raise ValueError('Expected 2–255 candidate actions')
if any(not isinstance(k,str) or not k.strip() or not isinstance(v,str) or not v.strip() for k,v in criteria.items()):
raise ValueError('Candidate IDs and descriptions must be nonempty text')
question_count+=1;path_count+=len(criteria)
if question_count>96 or path_count>256:
raise ValueError('Request exceeds 96 questions or 256 candidate paths')
return states
|