Beispiel #1
0
def respond(intent_request):
    """
    fulfill assign intent
    """
    output_session_attributes = intent_request[
        'sessionAttributes'] if intent_request[
            'sessionAttributes'] is not None else {}
    current_user = getSlackUserById(intent_request['userId'])
    runbook_id = get_slots(intent_request)["RunbookId"]
    assignee = get_slots(intent_request)["SlackUser"]

    runbook = getRunbookById(runbook_id)
    runlog_entry = Runlog.create(runbook_id, runbook['name'], assignee,
                                 current_user)
    save(runlog_entry)
    print('respond save runlog={}'.format(str(runlog_entry)))
    output_session_attributes['runlog'] = json.dumps(runlog_entry.__dict__)

    print('respond output_session_attributes={}, slots={}'.format(
        str(output_session_attributes), str(get_slots(intent_request))))
    return close(
        output_session_attributes, 'Fulfilled', {
            'contentType': 'PlainText',
            'content': 'Assigned \'' + runbook_id + '\' to ' + assignee
        })
Beispiel #2
0
def respond(intent_request):
    """
    Performs dialog management for delegating runlog to a user
    """
    intent = intent_request['currentIntent']['name']
    current_user = getSlackUserById(intent_request['userId'])
    source = intent_request['invocationSource']
    userInput = intent_request['inputTranscript'] if 'inputTranscript' in intent_request else None
    output_session_attributes = intent_request['sessionAttributes'] if intent_request['sessionAttributes'] is not None else {}

    #get runlog_id from user input or session
    runlog = None
    if userInput is not None and re.search('RL[0-9]+', userInput) is not None:
        #check if user has specified runbook id in utterance
        runlog_id=re.search('RL[0-9]+', userInput).group(0)
        intent_request['currentIntent']['slots']["RunlogId"]=runlog_id            
    elif 'runlog' in output_session_attributes:
        # get runlog from session if present
        runlog=json.loads(output_session_attributes['runlog'])
        runlog_id=runlog['runlogId']
        intent_request['currentIntent']['slots']["RunlogId"]=runlog['runlogId']
        
    #get slack user from user input or from slot (unlikely this will work)
    if re.search('@\w+', userInput) is not None:
        #check if user has specified @user in utterance
        intent_request['currentIntent']['slots']["SlackUser"]=re.search('@\w+', userInput).group(0)
    
    runbook_id=intent_request['currentIntent']['slots']['RunbookId'] if 'RunbookId' in intent_request['currentIntent']['slots'] else None
    assignee=intent_request['currentIntent']['slots']["SlackUser"] if 'SlackUser' in intent_request['currentIntent']['slots'] else None
    
    print('respond intentName={}, slots={}'.format(str(intent_request['currentIntent']['name']), str(get_slots(intent_request))))

    if source == 'DialogCodeHook':
        slots = get_slots(intent_request)

        validation_result = validate(runlog_id, assignee)
        print('respond validation result={}, invalid slot={}'.format(str(validation_result['isValid']),str(validation_result['violatedSlot'])))
        
        if not validation_result['isValid']:
            slots[validation_result['violatedSlot']] = None            
            
            if validation_result['violatedSlot']=='RunlogId':
                print('respond elicit-slot session={}, invalid slot={}'.format(str(output_session_attributes),str(validation_result['violatedSlot'])))
                return elicit_slot_with_text_message(output_session_attributes, intent, slots, validation_result['violatedSlot'], 'Invalid Runbook, please provide a valid Runbook ID')                
            else:
                print('respond elicit-slot session={}, invalid slot={}'.format(str(output_session_attributes),str(validation_result['violatedSlot'])))
                return elicit_slot_with_text_message(output_session_attributes, intent, slots, validation_result['violatedSlot'], 'Invalid slack user, mention slack users with \'@\' prefix')                
        else:
            runbook_id=getRunbookIdForRunlog(runlog_id, current_user)
            runbook=getRunbookById(runbook_id)
            runlog_entry = Runlog.assign(runbook_id, runbook['name'], current_user, assignee)
            save(runlog_entry)
            print('respond save runlog={}'.format(str(runlog_entry)))
            output_session_attributes['runlog']=json.dumps(runlog_entry.__dict__)

    print('respond intentName={}, slots={}, output_session_attributes={}'.format(str(intent_request['currentIntent']['name']), str(slots), str(output_session_attributes)))
    return delegate(output_session_attributes, get_slots(intent_request))
Beispiel #3
0
def respond(intent_request):
    """
    fulfill assign intent
    """
    output_session_attributes = intent_request['sessionAttributes'] if intent_request['sessionAttributes'] is not None else {}
    
    runbook_id = get_slots(intent_request)["RunbookId"]
    current_user = getSlackUserById(intent_request['userId'])

    print('respond::fulfill intentName={}, slots={}'.format(str(intent_request['currentIntent']['name']), str(get_slots(intent_request))))

    runbook=getRunbookById(runbook_id)
    runlog_entry = Runlog.create(runbook_id, runbook['name'], current_user, current_user)
    save(runlog_entry)
    print('respond save runlog={}'.format(str(runlog_entry)))
    output_session_attributes['runlog']=json.dumps(runlog_entry.__dict__)

    print('respond elicit_intent session={}, slots={}'.format(str(output_session_attributes), str(get_slots(intent_request))))
    buttons = [ 
        {"text":"Execute","value": "execute "+runlog_entry.runlogId}
    ]
    response_card = build_response_card('Execute '+runbook_id, runbook['name'], buttons)
    print('response elicit_intent_with_response_card = {}'.format(str(response_card)))

    return elicit_intent_with_response_card(output_session_attributes, 'Added \''+runbook_id+'\' to your TODOs, click Execute to run through now.', response_card)
Beispiel #4
0
def respond(intent_request):
    """
    Performs dialog management for assigning runbook to self and creating a runlog.
    """
    source = intent_request['invocationSource']
    intent = intent_request['currentIntent']['name']
    userInput = intent_request['inputTranscript']
    output_session_attributes = intent_request[
        'sessionAttributes'] if intent_request[
            'sessionAttributes'] is not None else {}

    #get runbook_id from user input or session
    if re.search('R[0-9]+', userInput) is not None:
        #check if user has specified runbook id in utterance
        runbook_id = re.search('R[0-9]+', userInput).group(0)
        intent_request['currentIntent']['slots']["RunbookId"] = runbook_id
    elif 'selected_runbook' in output_session_attributes:
        # get runbook from session if present
        runbook = json.loads(output_session_attributes['selected_runbook'])
        intent_request['currentIntent']['slots']["RunbookId"] = runbook['id']

    print('respond intentName={}, slots={}'.format(
        str(intent_request['currentIntent']['name']),
        str(get_slots(intent_request))))
    if source == 'DialogCodeHook':
        slots = get_slots(intent_request)

        runbook_id = intent_request['currentIntent']['slots']["RunbookId"]
        validation_result = validate(runbook_id)
        print('respond validation result={}, invalid slot={}'.format(
            str(validation_result['isValid']),
            str(validation_result['violatedSlot'])))
        if not validation_result['isValid']:
            slots[validation_result['violatedSlot']] = None

            if validation_result['violatedSlot'] == 'RunbookId':
                print('respond elicit-slot session={}, invalid slot={}'.format(
                    str(output_session_attributes),
                    str(validation_result['violatedSlot'])))
                return elicit_slot_with_text_message(
                    output_session_attributes, intent, slots,
                    validation_result['violatedSlot'],
                    'Invalid Runbook, please provide a valid Runbook ID')

    print('respond output_session_attributes={}, slots={}'.format(
        str(output_session_attributes), str(slots)))
    return delegate(output_session_attributes, get_slots(intent_request))
Beispiel #5
0
def respond(intent_request):
    """
    Performs dialog management for assigning runbook to a user
    """
    intent = intent_request['currentIntent']['name']
    source = intent_request['invocationSource']
    userInput = intent_request[
        'inputTranscript'] if 'inputTranscript' in intent_request else None
    output_session_attributes = intent_request[
        'sessionAttributes'] if intent_request[
            'sessionAttributes'] is not None else {}

    #get runbook_id from user input or session
    if userInput is not None and re.search('R[0-9]+', userInput) is not None:
        #check if user has specified runbook id in utterance
        intent_request['currentIntent']['slots']["RunbookId"] = re.search(
            'R[0-9]+', userInput).group(0)
    elif 'selected_runbook' in output_session_attributes:
        # get runbook from session if present
        runbook = json.loads(output_session_attributes['selected_runbook'])
        intent_request['currentIntent']['slots']["RunbookId"] = runbook['id']

    #get slack user from user input
    if userInput is not None and re.search('@\w+', userInput) is not None:
        #check if user has specified @user in utterance
        assignee = re.search('@\w+', userInput).group(0)
        intent_request['currentIntent']['slots']["SlackUser"] = assignee

    if source == 'DialogCodeHook':
        slots = get_slots(intent_request)
        print('respond intentName={}, slots={}'.format(
            str(intent_request['currentIntent']['name']), str(slots)))

        runbook_id = slots['RunbookId'] if 'RunbookId' in slots else None
        assignee = slots["SlackUser"] if 'SlackUser' in slots else None

        validation_result = validate(runbook_id, assignee)
        print('respond validation result={}, invalid slot={}'.format(
            str(validation_result['isValid']),
            str(validation_result['violatedSlot'])))

        if not validation_result['isValid']:
            slots[validation_result['violatedSlot']] = None

            if validation_result['violatedSlot'] == 'RunbookId':
                print('respond elicit-slot session={}, invalid slot={}'.format(
                    str(output_session_attributes),
                    str(validation_result['violatedSlot'])))
                return elicit_slot_with_text_message(
                    output_session_attributes, intent, slots,
                    validation_result['violatedSlot'],
                    'Invalid Runbook, please provide a valid Runbook ID')

            if validation_result['violatedSlot'] == 'SlackUser':
                print('respond elicit-slot session={}, invalid slot={}'.format(
                    str(output_session_attributes),
                    str(validation_result['violatedSlot'])))
                return elicit_slot_with_text_message(
                    output_session_attributes, intent, slots,
                    validation_result['violatedSlot'],
                    'Invalid slack user, mention slack users with \'@\' prefix'
                )

    print('respond output_session_attributes={}, slots={}'.format(
        str(output_session_attributes), str(slots)))
    return delegate(output_session_attributes, get_slots(intent_request))
Beispiel #6
0
def respond(intent_request):
    """
    Performs dialog management for executing runlog
    """
    current_user = getSlackUserById(intent_request['userId'])
    source = intent_request['invocationSource']
    userInput = intent_request['inputTranscript']
    intent = intent_request['currentIntent']['name']
    output_session_attributes = intent_request[
        'sessionAttributes'] if intent_request[
            'sessionAttributes'] is not None else {}

    #get runlog_id from user input or session or from slot
    runlog_id = get_slots(
        intent_request)["RunlogId"] if 'RunlogId' in get_slots(
            intent_request) else None
    if runlog_id is None:
        if re.search('RL[0-9]+', userInput) is not None:
            #check if user has specified runlog id in utterance
            runlog_id = re.search('RL[0-9]+', userInput).group(0)
            intent_request['currentIntent']['slots']["RunlogId"] = runlog_id
        elif 'runlog' in output_session_attributes:
            # get runlog from session if present
            runlog = json.loads(output_session_attributes['runlog'])
            runlog_id = runlog['runlogId']
            intent_request['currentIntent']['slots']["RunlogId"] = runlog_id

    isDone = re.match('(?i)DONE', userInput)
    intent_request['currentIntent']['slots']['IsDone'] = isDone

    if source == 'DialogCodeHook':
        print('respond intentName={}, slots={}'.format(
            str(intent_request['currentIntent']['name']),
            str(get_slots(intent_request))))
        slots = get_slots(intent_request)

        if not runlog_id:
            print('respond elicit-slot session={}, invalid slot={}'.format(
                str(output_session_attributes), 'RunlogId'))
            return elicit_slot_with_text_message(
                output_session_attributes, intent, slots, 'RunlogId',
                'Invalid RunlogID, please provide a valid RunlogID')

        exec_context = ExecutionContext(runlog_id, current_user)
        runbook = exec_context.getRunbook()
        step_index, task_index, step = exec_context.getNextStepAndTask()

        if step is not None:
            #build response card to display step and task information
            buttons = [{
                "text": "Done",
                "value": "execute " + runlog_id
            }, {
                "text": "Raise Issue",
                "value": "raise error " + runlog_id
            }]
            response_card = build_response_card(
                runbook['name'] + ': Step ' + str(
                    (step_index + 1)) + ' of ' + str(len(runbook['steps'])),
                ' Task ' + str(task_index + 1), buttons)
            print('response elicit_intent_with_response_card = {}'.format(
                str(response_card)))

            runlog_entry = Runlog.start(
                runlog_id, runbook['steps'][step_index]['id'],
                runbook['steps'][step_index]['tasks'][task_index], 'TASK',
                current_user, current_user)
            save(runlog_entry)
            print('respond save runlog={}'.format(str(runlog_entry)))
            output_session_attributes['runlog'] = json.dumps(
                runlog_entry.__dict__)
            print('respond output_session_attributes={}'.format(
                str(output_session_attributes)))

            task_text = runbook['steps'][step_index]['tasks'][task_index]
            return elicit_intent_with_response_card(output_session_attributes,
                                                    task_text, response_card)

    return close(output_session_attributes, 'Fulfilled', {
        'contentType': 'PlainText',
        'content': 'You have completed this task.'
    })
Beispiel #7
0
def respond(intent_request):
    """
    Performs dialog management for listing runlogs querying for resolution
    """
    intent = intent_request['currentIntent']['name']
    current_user = getSlackUserById(intent_request['userId'])
    userInput = intent_request['inputTranscript']
    source = intent_request['invocationSource']
    output_session_attributes = intent_request[
        'sessionAttributes'] if intent_request[
            'sessionAttributes'] is not None else {}

    runlog_id = get_slots(
        intent_request)['RunlogId'] if 'RunlogId' in get_slots(
            intent_request) else None
    if runlog_id is None:
        if re.search('RL[0-9]+', userInput) is not None:
            #check if user has specified runlog id in utterance
            runlog_id = re.search('RL[0-9]+', userInput).group(0)
            intent_request['currentIntent']['slots']["RunlogId"] = runlog_id
        elif 'runlog' in output_session_attributes:
            # get runlog from session if present
            runlog = json.loads(output_session_attributes['runlog'])
            runlog_id = runlog['runlogId']
            intent_request['currentIntent']['slots']["RunlogId"] = runlog_id

    resolve_issue = get_slots(
        intent_request)['ResolveIssue'] if 'ResolveIssue' in get_slots(
            intent_request) else None
    add_resolution = get_slots(
        intent_request)['AddResolution'] if 'AddResolution' in get_slots(
            intent_request) else None

    if source == 'DialogCodeHook':
        log = getLastRunlogEntryById(
            runlog_id)  #search for last runlog entry with issue description

        if not resolve_issue:
            buttons = [{"text": "Mark Resolved", "value": "resolve-issue"}]
            response_card = build_response_card(
                log['runlogId'] + "-" + log['resolution']['summary'],
                log['resolution']['description'], buttons)

            return elicit_slot_with_response_card(
                output_session_attributes, intent, get_slots(intent_request),
                'ResolveIssue',
                Issue(log['resolution']['issueType'],
                      log['resolution']['severity'],
                      log['resolution']['environment'],
                      log['resolution']['summary'],
                      log['resolution']['description'],
                      add_resolution).__dict__, response_card)

        if resolve_issue == "resolve-issue":
            last_task_entry = getLastRunlogEntry(runlog_id, 'TASK',
                                                 current_user)
            runlog_entry = Runlog.resolve(
                runlog_id, last_task_entry.id, last_task_entry.name, 'TASK',
                current_user, last_task_entry.originator,
                'Resolution found for issue :\n' +
                log['resolution']['summary'], None,
                json.dumps(
                    Issue(log['resolution']['issueType'],
                          log['resolution']['severity'],
                          log['resolution']['environment'],
                          log['resolution']['summary'],
                          log['resolution']['description'],
                          add_resolution).__dict__),
                last_task_entry.resolutionCount)
            save(runlog_entry)
            print('respond save runlog={}'.format(str(runlog_entry)))
            output_session_attributes['runlog'] = json.dumps(
                runlog_entry.__dict__)
            return close(
                output_session_attributes, 'Fulfilled', {
                    'contentType': 'PlainText',
                    'content': '''Resolution has been added'''
                })
Beispiel #8
0
def respond(intent_request):
    """
    Performs dialog management for searching and selecting a runbook.
    """
    product = get_slots(intent_request)["Product"]
    runbook_type = get_slots(intent_request)["RunbookType"]
    action = get_slots(intent_request)["ActionType"]
    runbook_id = get_slots(intent_request)["RunbookId"]
    
    print('respond intentName={}, slots={}'.format(str(intent_request['currentIntent']['name']), str(get_slots(intent_request))))

    source = intent_request['invocationSource']    
    intent = intent_request['currentIntent']['name']
    output_session_attributes = intent_request['sessionAttributes'] if intent_request['sessionAttributes'] is not None else {}
	
    if source == 'DialogCodeHook':
        slots = get_slots(intent_request)

        validation_result = validate(product, runbook_type, action, runbook_id)
        print('respond validation result={}, invalid slot={}'.format(str(validation_result['isValid']),str(validation_result['violatedSlot'])))
        
        if not validation_result['isValid']:
            slots[validation_result['violatedSlot']] = None
            
            # elicit slot for product            
            if validation_result['violatedSlot']=='Product':
                buttons = [ {"text":f['key'].upper()+' ('+str(f['doc_count'])+')',"value":f['key']} for f in getAllRunbooks()['facets']['product']['buckets'] ]
                response_card = build_response_card('Filter by Product/Platform','Select from the following products/platforms', buttons)
                
                print('respond elicit-slot response_card={}, invalid slot={}'.format(str(response_card),str(validation_result['violatedSlot'])))
                return elicit_slot_with_response_card(output_session_attributes,
                               intent,
                               slots,
                               validation_result['violatedSlot'],
                               'Please select from below products',
                               response_card)
                
    
            if validation_result['violatedSlot']=='RunbookId':                
                result = searchByName(None, product, runbook_type, action) #search for runbooks with current slots                
                attachments=[]
                for rbk in result['runbooks']:                    
                    buttons = [ {"text":"Select "+rbk['id'], "value":rbk['id']} ]
                    response_card = { 'title': (rbk['id']+': '+rbk['name']), 'subTitle' : rbk['description'][:75], 'options': buttons }
                    attachments.insert(0, response_card)
                
                response_cards=build_multiple_response_cards(attachments)
                
                print('respond elicit-slot response_cards={}, invalid slot={}'.format(str(response_cards),str(validation_result['violatedSlot'])))
                return elicit_slot_with_response_card(output_session_attributes,
                               intent,
                               slots,
                               validation_result['violatedSlot'],
                               'Please select from below list',
                               response_cards)


        if runbook_id:
            output_session_attributes['selected_runbook'] = json.dumps(getRunbookById(runbook_id)) # serialize runbook obj
            output_session_attributes['previous_intent'] = intent_request['currentIntent']['name']
                        
        print('respond elicit_intent session={}'.format(str(output_session_attributes)))
        # select runbook, and rely on the goodbye message of the bot to define the message to the end user.
        buttons = [ 
                    {"text":"View Details","value": "get "+runbook_id}, 
                    {"text":"Assign to","value": "assign "+runbook_id}, 
                    {"text":"Execute","value": "to do "+runbook_id}
        ]
        response_card = build_response_card('Runbook '+runbook_id, getRunbookById(runbook_id)['name'], buttons)
        print('response elicit_intent_with_response_card = {}'.format(str(response_card)))
    
        return elicit_intent_with_response_card(output_session_attributes, 'Now that you have selected a runbook, what do you want to do next?', response_card)
Beispiel #9
0
def respond(intent_request):
    """
    Raises issue encountered while executing the runbook
    
    """
    intent = intent_request['currentIntent']['name']    
    current_user = getSlackUserById(intent_request['userId'])
    userInput = intent_request['inputTranscript']
    source = intent_request['invocationSource']    
    output_session_attributes = intent_request['sessionAttributes'] if intent_request['sessionAttributes'] is not None else {}
    
    #get runlog_id from user input or session or from slot
    runlog_id = get_slots(intent_request)["RunlogId"] if 'RunlogId' in get_slots(intent_request) else None
    if runlog_id is None:
        if re.search('RL[0-9]+', userInput) is not None:
            #check if user has specified runlog id in utterance
            runlog_id=re.search('RL[0-9]+', userInput).group(0)
            intent_request['currentIntent']['slots']["RunlogId"]=runlog_id
        elif 'runlog' in output_session_attributes:
            # get runlog from session if present
            runlog=json.loads(output_session_attributes['runlog'])
            runlog_id=runlog['runlogId']
            intent_request['currentIntent']['slots']["RunlogId"]=runlog_id    
    
    issue_type = get_slots(intent_request)["IssueType"] if 'IssueType' in get_slots(intent_request) else None
    severity = get_slots(intent_request)["Severity"] if 'Severity' in get_slots(intent_request) else None
    environment = get_slots(intent_request)["Environment"] if 'Environment' in get_slots(intent_request) else None
    summary = get_slots(intent_request)["Summary"] if 'Summary' in get_slots(intent_request) else None
    description = get_slots(intent_request)["Description"] if 'Description' in get_slots(intent_request) else None
    
    resolution_id =get_slots(intent_request)["ResolutionId"]  if 'ResolutionId' in get_slots(intent_request) else None
    confirm_resolution = get_slots(intent_request)["ConfirmResolution"] if 'ConfirmResolution' in get_slots(intent_request) else None
    confirm_assign = get_slots(intent_request)["ConfirmAssign"] if 'ConfirmAssign' in get_slots(intent_request) else None
    
    assignee = get_slots(intent_request)["SlackUser"] if 'SlackUser' in get_slots(intent_request) else None
    if assignee is None and re.search('@\w+', userInput) is not None:
        #check if user has specified @user in utterance
        assignee=re.search('@\w+', userInput).group(0)
        intent_request['currentIntent']['slots']["SlackUser"]=assignee
       
    if source == 'DialogCodeHook':
        slots = get_slots(intent_request)        

        if issue_type and severity and environment and summary and description:
            last_task_entry = getLastRunlogEntry(runlog_id, 'TASK', current_user)
            runlog_entry = Runlog.raise_error(runlog_id, last_task_entry['id'], last_task_entry['name'], 'TASK', current_user, last_task_entry['originator'], summary, 
                                             None, json.dumps(Issue(issue_type, severity, environment, summary, description).__dict__))
            save(runlog_entry)
            print('respond save runlog={}'.format(str(runlog_entry)))
            output_session_attributes['runlog']=json.dumps(runlog_entry.__dict__)
            
        resolution_list = getResolution(runlog_id)
        
        if not resolution_id: 
                attachments=[]
                for resolution in resolution_list:                    
                    buttons = [ {"text":"Select "+resolution['id'], "value":resolution['id']} ]
                    response_card = { 'title': (resolution['source']), 'subTitle' :resolution['resolution'][:75]+"...", 'options': buttons }
                    attachments.insert(0, response_card)
                
                response_cards=build_multiple_response_cards(attachments)
                return elicit_slot_with_response_card(output_session_attributes,
                               intent,
                               slots,
                               'ResolutionId',
                               'Please select from below list',
                               response_cards)        
        
        resolution = [item for item in resolution_list if resolution_id == item['id']][0] #TODO
                                   
        if not confirm_resolution:
            buttons = [{"text":"yes","value":"yes"},{"text":"no","value":"no"}]
            response_card = build_response_card('Details','Resolution available',buttons)
            return elicit_slot_with_response_card(output_session_attributes,
                               intent,
                               slots,
                               'ConfirmResolution',
                               resolution['resolution']+'\n Did this resolve the issue?',response_card)
                               
        if confirm_resolution=="yes" and resolution['source'] == "stackoverflow":
            runlog_entry = Runlog.resolve(runlog_id, last_task_entry.id, last_task_entry.name, 'TASK', current_user, last_task_entry.originator, 'Resolution found for issue :\n'+summary, 
                                              None,json.dumps(Issue(issue_type, severity, environment, summary, description)),last_task_entry.resolutionCount)
            save(runlog_entry)
            print('respond save runlog={}'.format(str(runlog_entry)))
            output_session_attributes['runlog']=json.dumps(runlog_entry.__dict__)
            
        if confirm_resolution=="yes" and resolution['source'] == "runlog":
            runlog_entry = Runlog.resolve(runlog_id, last_task_entry.id, last_task_entry.name, 'TASK', current_user, last_task_entry.originator, summary, 
                                              None,json.dumps(Issue(issue_type, severity, environment, summary, description)),last_task_entry.resolutionCount+1)
            save(runlog_entry)
            print('respond save runlog={}'.format(str(runlog_entry)))
            output_session_attributes['runlog']=json.dumps(runlog_entry.__dict__)
            
        if confirm_resolution=="no" and not confirm_assign:
            buttons = [{"text":"yes","value":"yes"},{"text":"no","value":"no"}]
            response_card = build_response_card('Delegate issue to user','Choose one',buttons)
            return elicit_slot_with_response_card(output_session_attributes,
                               intent,
                               slots,
                               'ConfirmAssign',
                               'Do you want to delegate this issue to someone?',response_card)
                               
        if assignee is not None and confirm_assign=="yes":
            runlog_entry = Runlog.assign( runlog_id, last_task_entry.id, last_task_entry.name,  last_task_entry.originator, assignee)
            save(runlog_entry)
            print('respond save runlog={}'.format(str(runlog_entry)))
            output_session_attributes['runlog']=json.dumps(runlog_entry.__dict__)
        
        # TODO add functionality when user doesn't want to assign issue
        if confirm_assign =="no":                        
            return delegate(output_session_attributes, get_slots(intent_request))
        
    print('respond close session={}'.format(str(output_session_attributes)))
    return close(output_session_attributes, 'Fulfilled', {'contentType': 'PlainText', 'content': 'Noted your issue'})