diff --git a/README.md b/README.md
index 80b16ff..5e70b90 100644
--- a/README.md
+++ b/README.md
@@ -32,6 +32,8 @@ Currently supported providers:
- Multiple provider integration
- Customizable
+
+
## Known Limitations
- Tested only on 7.52 & ABAP 2022 - **experimental** downport available in branch 702
diff --git a/src/yy_llm_ide.prog.abap b/src/yy_llm_ide.prog.abap
new file mode 100644
index 0000000..18df5b3
--- /dev/null
+++ b/src/yy_llm_ide.prog.abap
@@ -0,0 +1,694 @@
+*&---------------------------------------------------------------------*
+*& Include YY_LLM_IDE
+*&---------------------------------------------------------------------*
+
+CONSTANTS:
+ c_llm_untitled TYPE programm VALUE 'Untitled LLM Model',
+ c_new_abap_editor TYPE flag VALUE abap_true,
+ c_source_type TYPE string VALUE 'LISP'.
+
+DATA g_ok_code TYPE syucomm.
+
+INTERFACE lif_unit_test.
+ENDINTERFACE.
+
+TYPES: BEGIN OF ts_settings,
+ stack TYPE string_table,
+ new_editor TYPE flag,
+ END OF ts_settings.
+
+CLASS lcl_stack DEFINITION FRIENDS lif_unit_test.
+ PUBLIC SECTION.
+ TYPES tv_data TYPE string.
+
+ METHODS constructor IMPORTING it_stack TYPE string_table OPTIONAL.
+ METHODS previous RETURNING VALUE(rv_data) TYPE tv_data.
+ METHODS next RETURNING VALUE(rv_data) TYPE tv_data.
+
+ METHODS push IMPORTING iv_key TYPE tv_data.
+
+ METHODS serialize RETURNING VALUE(rt_string) TYPE string_table.
+ METHODS deserialize IMPORTING it_string TYPE string_table.
+ PROTECTED SECTION.
+ DATA mt_stack TYPE string_table.
+ DATA mv_index TYPE i.
+ENDCLASS.
+
+CLASS lcl_stack IMPLEMENTATION.
+
+ METHOD constructor.
+ mt_stack = it_stack.
+ ENDMETHOD.
+
+ METHOD push.
+ CHECK iv_key IS NOT INITIAL.
+ APPEND iv_key TO mt_stack.
+ mv_index = lines( mt_stack ).
+ ENDMETHOD.
+
+ METHOD previous.
+ IF mv_index GT 1.
+ mv_index = mv_index - 1.
+ ENDIF.
+ rv_data = VALUE #( mt_stack[ mv_index ] OPTIONAL ).
+ ENDMETHOD.
+
+ METHOD next.
+ IF mv_index LT lines( mt_stack ).
+ mv_index = mv_index + 1.
+ ENDIF.
+ rv_data = VALUE #( mt_stack[ mv_index ] OPTIONAL ).
+ ENDMETHOD.
+
+ METHOD deserialize.
+ mt_stack = it_string.
+ mv_index = lines( mt_stack ).
+ ENDMETHOD.
+
+ METHOD serialize.
+ rt_string = mt_stack.
+ ENDMETHOD.
+
+ENDCLASS.
+
+INTERFACE lif_source_editor.
+ METHODS clear.
+ METHODS push_text.
+ METHODS previous.
+ METHODS next.
+ METHODS to_string RETURNING VALUE(rv_text) TYPE string.
+ METHODS update_status IMPORTING iv_string TYPE string.
+ METHODS setup IMPORTING is_settings TYPE ts_settings.
+
+ METHODS set_focus.
+ METHODS free RETURNING VALUE(rt_string) TYPE string_table.
+ENDINTERFACE.
+
+*----------------------------------------------------------------------*
+* CLASS lcl_editor DEFINITION
+*----------------------------------------------------------------------*
+CLASS lcl_editor DEFINITION INHERITING FROM cl_gui_textedit.
+ PUBLIC SECTION.
+ CONSTANTS c_max_line_count TYPE i VALUE 10000.
+
+ METHODS constructor IMPORTING io_container TYPE REF TO cl_gui_container
+ iv_read_only TYPE flag DEFAULT abap_true
+ iv_toolbar TYPE flag DEFAULT abap_false.
+ METHODS append_source IMPORTING iv_text TYPE string.
+
+ INTERFACES lif_source_editor.
+
+ METHODS append_string IMPORTING iv_text TYPE string.
+ PROTECTED SECTION.
+ DATA mv_counter TYPE i.
+ DATA mo_stack TYPE REF TO lcl_stack.
+
+ METHODS format_input IMPORTING query TYPE string
+ RETURNING VALUE(rv_text) TYPE string.
+ENDCLASS.
+
+*----------------------------------------------------------------------*
+* CLASS lcl_editor IMPLEMENTATION
+*----------------------------------------------------------------------*
+CLASS lcl_editor IMPLEMENTATION.
+
+ METHOD constructor.
+ DATA mode TYPE i.
+ io_container->set_visible( abap_true ).
+ super->constructor( io_container ).
+ IF iv_toolbar EQ abap_true.
+ mode = 1.
+ ELSE.
+ mode = 0.
+ ENDIF.
+ set_toolbar_mode( mode ).
+ cl_gui_cfw=>flush( ).
+
+ IF iv_read_only EQ abap_true.
+ set_readonly_mode( cl_gui_textedit=>true ).
+ mode = 0.
+ ELSE.
+ mode = 1.
+ ENDIF.
+ set_statusbar_mode( mode ).
+* Work around to avoid NO DATA dump on first read
+ lif_source_editor~clear( ).
+ mo_stack = NEW #( ).
+ ENDMETHOD. "constructor
+
+ METHOD lif_source_editor~clear.
+ delete_text( ).
+ ENDMETHOD. "append_string
+
+ METHOD append_string.
+ DATA lv_text TYPE string.
+ lv_text = lif_source_editor~to_string( ).
+ CONCATENATE lv_text iv_text INTO lv_text RESPECTING BLANKS.
+ set_textstream( lv_text ).
+ go_to_line( c_max_line_count ).
+ ENDMETHOD.
+
+ METHOD format_input.
+ ADD 1 TO mv_counter.
+ rv_text = | ${ mv_counter }> { query }\n|.
+ ENDMETHOD. "format_input
+
+ METHOD append_source.
+ append_string( format_input( iv_text ) ).
+ ENDMETHOD. "append_string
+
+ METHOD lif_source_editor~to_string.
+ get_textstream( IMPORTING text = rv_text
+ EXCEPTIONS OTHERS = 1 ).
+ CHECK sy-subrc EQ 0.
+ cl_gui_cfw=>flush( ).
+ ENDMETHOD. "to_string
+
+ METHOD lif_source_editor~update_status.
+ DATA lv_text TYPE char72.
+ lv_text = iv_string.
+ set_status_text( lv_text ).
+ ENDMETHOD. "update_status
+
+ METHOD lif_source_editor~push_text.
+ DATA code TYPE string.
+ code = lif_source_editor~to_string( ).
+ CHECK code NE space.
+ mo_stack->push( code ).
+ lif_source_editor~clear( ).
+ ENDMETHOD.
+
+ METHOD lif_source_editor~previous.
+ lif_source_editor~clear( ).
+ append_string( mo_stack->previous( ) ).
+ ENDMETHOD.
+
+ METHOD lif_source_editor~next.
+ lif_source_editor~clear( ).
+ append_string( mo_stack->next( ) ).
+ ENDMETHOD.
+
+ METHOD lif_source_editor~set_focus.
+ set_focus( EXPORTING control = me
+ EXCEPTIONS OTHERS = 0 ).
+ ENDMETHOD.
+
+ METHOD lif_source_editor~free.
+ free( ).
+ rt_string = mo_stack->serialize( ).
+ ENDMETHOD.
+
+ METHOD lif_source_editor~setup.
+ mo_stack->deserialize( is_settings-stack ).
+ ENDMETHOD.
+
+ENDCLASS. "lcl_editor IMPLEMENTATION
+
+CLASS lcl_console DEFINITION INHERITING FROM lcl_editor.
+ PUBLIC SECTION.
+ METHODS constructor IMPORTING io_container TYPE REF TO cl_gui_container
+ iv_toolbar TYPE flag DEFAULT abap_false.
+ METHODS set_textstream REDEFINITION.
+ METHODS lif_source_editor~to_string REDEFINITION.
+ PROTECTED SECTION.
+ PRIVATE SECTION.
+ DATA mv_content TYPE string.
+ENDCLASS.
+
+
+CLASS lcl_console IMPLEMENTATION.
+
+ METHOD constructor.
+ super->constructor( io_container = io_container
+ iv_read_only = abap_true
+ iv_toolbar = iv_toolbar ).
+ ENDMETHOD.
+
+ METHOD set_textstream.
+ super->set_textstream( text ).
+ mv_content = text.
+ ENDMETHOD.
+
+ METHOD lif_source_editor~to_string.
+ rv_text = mv_content.
+ ENDMETHOD. "to_string
+
+ENDCLASS.
+
+CLASS lcl_source DEFINITION INHERITING FROM cl_gui_sourceedit.
+ PUBLIC SECTION.
+ METHODS constructor IMPORTING io_container TYPE REF TO cl_gui_container
+ iv_read_only TYPE flag DEFAULT abap_false
+ iv_toolbar TYPE flag DEFAULT abap_false
+ iv_title TYPE string.
+ INTERFACES lif_source_editor.
+ PRIVATE SECTION.
+ DATA mo_stack TYPE REF TO lcl_stack.
+ENDCLASS.
+
+CLASS lcl_source IMPLEMENTATION.
+
+ METHOD constructor.
+ DATA mode TYPE i.
+ DATA exception_name TYPE string.
+
+ io_container->set_visible( abap_true ).
+ super->constructor(
+ EXPORTING
+ parent = io_container
+ max_number_chars = '255'
+ EXCEPTIONS
+ error_cntl_create = 1
+ error_dp_create = 2
+ gui_type_not_supported = 3
+ error_cntl_init = 4 ).
+
+ IF sy-subrc NE 0.
+ CASE sy-subrc.
+ WHEN 1.
+ exception_name = 'ERROR_CNTL_CREATE'.
+ WHEN 2.
+ exception_name = 'ERROR_DP_CREATE'.
+ WHEN 3.
+ exception_name = 'GUI_TYPE_NOT_SUPPORTED'.
+ WHEN 4.
+ exception_name = 'ERROR_CNTL_INIT'.
+ ENDCASE.
+ RAISE EXCEPTION TYPE cx_coverage_api_adapter.
+ ENDIF.
+
+ set_source_type( c_source_type ).
+ IF iv_toolbar EQ abap_true.
+ mode = 1.
+ ELSE.
+ mode = 0.
+ ENDIF.
+ set_toolbar_mode( mode ).
+ cl_gui_cfw=>flush( ).
+
+ IF iv_read_only EQ abap_true.
+ set_readonly_mode( cl_gui_textedit=>true ).
+ mode = 0.
+ ELSE.
+ mode = 1.
+ ENDIF.
+ set_statusbar_mode( mode ).
+ set_actual_name( CONV syrepid( iv_title ) ).
+ upload_properties( EXCEPTIONS OTHERS = 1 ).
+ IF sy-subrc <> 0.
+* MESSAGE e215(ed).
+ ENDIF.
+ create_document( ).
+
+* Work around to avoid NO DATA dump on first read
+ lif_source_editor~clear( ).
+
+ CREATE OBJECT mo_stack.
+ ENDMETHOD. "constructor
+
+ METHOD lif_source_editor~set_focus.
+ set_focus( EXPORTING control = me
+ EXCEPTIONS OTHERS = 0 ).
+ ENDMETHOD.
+
+ METHOD lif_source_editor~free.
+ free( ).
+ rt_string = mo_stack->serialize( ).
+ ENDMETHOD.
+
+ METHOD lif_source_editor~setup.
+ mo_stack->deserialize( is_settings-stack ).
+ ENDMETHOD.
+
+ METHOD lif_source_editor~to_string.
+ DATA lt_text TYPE STANDARD TABLE OF string.
+
+ get_text( IMPORTING table = lt_text
+ EXCEPTIONS OTHERS = 0 ).
+ "cl_gui_cfw=>flush( ).
+ rv_text = concat_lines_of( table = lt_text sep = |\n| ).
+ ENDMETHOD. "to_string
+
+ METHOD lif_source_editor~update_status.
+ MESSAGE iv_string TYPE 'S'.
+ ENDMETHOD. "update_status
+
+ METHOD lif_source_editor~clear.
+ DATA lt_text TYPE STANDARD TABLE OF string.
+
+ set_text( EXPORTING table = lt_text
+ EXCEPTIONS OTHERS = 0 ).
+ ENDMETHOD.
+
+ METHOD lif_source_editor~push_text.
+ DATA code TYPE string.
+ code = lif_source_editor~to_string( ).
+ CHECK code NE space.
+ mo_stack->push( code ).
+ lif_source_editor~clear( ).
+ ENDMETHOD.
+
+ METHOD lif_source_editor~previous.
+ DATA lt_text TYPE STANDARD TABLE OF string.
+
+ APPEND mo_stack->previous( ) TO lt_text.
+ set_text( EXPORTING table = lt_text
+ EXCEPTIONS OTHERS = 0 ).
+ ENDMETHOD.
+
+ METHOD lif_source_editor~next.
+ DATA lt_text TYPE STANDARD TABLE OF string.
+
+ APPEND mo_stack->next( ) TO lt_text.
+ set_text( EXPORTING table = lt_text
+ EXCEPTIONS OTHERS = 0 ).
+ ENDMETHOD.
+
+ENDCLASS.
+
+*----------------------------------------------------------------------*
+* CLASS lcl_container DEFINITION
+*----------------------------------------------------------------------*
+CLASS lcl_container DEFINITION.
+ PUBLIC SECTION.
+ METHODS constructor.
+ METHODS free_controls.
+ DATA mo_input TYPE REF TO cl_gui_container READ-ONLY.
+ DATA mo_output TYPE REF TO cl_gui_container READ-ONLY.
+ DATA mo_console TYPE REF TO cl_gui_container READ-ONLY.
+ PRIVATE SECTION.
+ DATA mo_splitter_h TYPE REF TO cl_gui_splitter_container.
+ DATA mo_splitter_v TYPE REF TO cl_gui_splitter_container.
+ DATA mo_left TYPE REF TO cl_gui_container.
+ENDCLASS.
+
+CLASS lcl_container IMPLEMENTATION.
+ METHOD constructor.
+ " Splitter Container
+ mo_splitter_v = NEW #( link_dynnr = '0100'
+ link_repid = sy-repid
+ parent = cl_gui_container=>screen0
+ rows = 1
+ columns = 2 ).
+ mo_splitter_v->set_border( border = cl_gui_cfw=>false ).
+
+ mo_splitter_v->set_column_mode( mode = mo_splitter_v->mode_absolute ).
+ mo_splitter_v->set_column_width( id = 1
+ width = 750 ).
+ mo_left = mo_splitter_v->get_container( row = 1
+ column = 1 ).
+ mo_console = mo_splitter_v->get_container( row = 1
+ column = 2 ).
+
+ mo_splitter_h = NEW #( parent = mo_left
+ rows = 2
+ columns = 1 ).
+ mo_splitter_h->set_border( border = cl_gui_cfw=>false ).
+ mo_splitter_h->set_row_mode( mode = mo_splitter_v->mode_relative ).
+
+ mo_input = mo_splitter_h->get_container( row = 1
+ column = 1 ).
+ mo_output = mo_splitter_h->get_container( row = 2
+ column = 1 ).
+
+ ENDMETHOD.
+
+ METHOD free_controls.
+ FREE: mo_input,
+ mo_output,
+ mo_console.
+ FREE mo_left.
+ FREE mo_splitter_h.
+ FREE mo_splitter_v.
+ ENDMETHOD. "free_controls
+
+ENDCLASS. "lcl_container IMPLEMENTATION
+
+CLASS lcl_app DEFINITION.
+ PUBLIC SECTION.
+ DATA mv_title TYPE string VALUE c_llm_untitled READ-ONLY.
+
+ CLASS-METHODS:
+ chat,
+ free,
+ default_model RETURNING VALUE(rd_model) TYPE zllm_clnt_config-provider_model,
+ pbo,
+ pai IMPORTING id_code TYPE syucomm
+ RETURNING VALUE(rd_flag) TYPE flag.
+
+ METHODS constructor.
+ METHODS first_output.
+ METHODS free_controls.
+ METHODS handle_user_command IMPORTING ucomm TYPE sy-ucomm
+ RETURNING VALUE(rd_flag) TYPE flag.
+
+ PRIVATE SECTION.
+ CLASS-DATA app TYPE REF TO lcl_app.
+
+ DATA mv_first TYPE flag VALUE abap_true.
+ DATA mo_cont TYPE REF TO lcl_container.
+ DATA mi_source TYPE REF TO lif_source_editor.
+ DATA mo_output TYPE REF TO lcl_editor.
+ DATA mo_console TYPE REF TO lcl_console.
+ DATA ms_settings TYPE ts_settings.
+
+ CLASS-METHODS call_transaction IMPORTING id_transaction TYPE tcode.
+ METHODS welcome RETURNING VALUE(text) TYPE string.
+ METHODS console_header RETURNING VALUE(text) TYPE string.
+ METHODS refresh.
+
+ METHODS new_source_editor IMPORTING io_cont TYPE REF TO cl_gui_container
+ RETURNING VALUE(ri_source) TYPE REF TO lif_source_editor.
+ METHODS previous.
+ METHODS next.
+ METHODS evaluate.
+
+ DATA runtime TYPE i.
+
+ METHODS read_time RETURNING VALUE(rd_time) TYPE i.
+ENDCLASS.
+
+*&---------------------------------------------------------------------*
+*& Module STATUS_0100 OUTPUT
+*&---------------------------------------------------------------------*
+MODULE status_0100 OUTPUT.
+ lcl_app=>pbo( ).
+ENDMODULE.
+*&---------------------------------------------------------------------*
+*& Module USER_COMMAND_0100 INPUT
+*&---------------------------------------------------------------------*
+MODULE user_command_0100 INPUT.
+ CHECK lcl_app=>pai( g_ok_code ).
+ CLEAR g_ok_code.
+ENDMODULE.
+
+MODULE cancel_0100 INPUT.
+ lcl_app=>free( ).
+ LEAVE PROGRAM.
+ENDMODULE.
+
+CLASS lcl_app IMPLEMENTATION.
+
+ METHOD constructor.
+ super->constructor( ).
+ mv_title = model.
+
+ CREATE OBJECT:
+ mo_cont,
+
+ mo_output
+ EXPORTING
+ io_container = mo_cont->mo_output
+ iv_toolbar = abap_true,
+ mo_console
+ EXPORTING
+ io_container = mo_cont->mo_console.
+
+ mi_source = new_source_editor( io_cont = mo_cont->mo_input ).
+ refresh( ).
+ ENDMETHOD.
+
+ METHOD read_time.
+ GET RUN TIME FIELD rd_time.
+ ENDMETHOD.
+
+ METHOD first_output.
+ CHECK mv_first EQ abap_true.
+ CLEAR mv_first.
+ mi_source->set_focus( ).
+ mo_output->append_string( |{ welcome( ) }\n| ).
+ mo_console->append_string( console_header( ) ).
+ ENDMETHOD.
+
+ METHOD free_controls.
+ mo_console->free( ).
+ mo_output->free( ).
+ ms_settings-stack = mi_source->free( ).
+ mo_cont->free_controls( ).
+ "save_settings( ).
+ ENDMETHOD.
+
+ METHOD welcome.
+ text = |==> Welcome to LLM Chat!\n|.
+ ENDMETHOD. "welcome
+
+ METHOD console_header.
+ text = |==> LLM -- Console { sy-uname } -- { sy-datlo DATE = ENVIRONMENT } { sy-uzeit TIME = ENVIRONMENT }\n|.
+ ENDMETHOD.
+
+ METHOD new_source_editor.
+ DATA gui_support TYPE boolean.
+* Check for frontend support for the new ABAP Editor
+ cl_gui_frontend_services=>check_gui_support(
+ EXPORTING
+ component = 'abapeditor' "#EC NOTEXT
+ feature_name = 'ab4' "#EC NOTEXT
+ RECEIVING
+ result = gui_support
+ EXCEPTIONS
+ cntl_error = 1
+ error_no_gui = 2
+ wrong_parameter = 3
+ not_supported_by_gui = 4
+ unknown_error = 5
+ OTHERS = 6 ).
+ IF sy-subrc NE 0 OR gui_support NE abap_true OR c_new_abap_editor NE abap_true.
+ ri_source = NEW lcl_editor(
+ io_container = io_cont
+ iv_read_only = abap_false
+ iv_toolbar = abap_true ).
+
+ ELSE.
+ ri_source = NEW lcl_source(
+ io_container = io_cont
+ iv_read_only = abap_false
+ iv_toolbar = abap_true
+ iv_title = mv_title ).
+ ENDIF.
+ ri_source->setup( ms_settings ).
+
+ ENDMETHOD.
+
+ METHOD previous.
+ mi_source->previous( ).
+ ENDMETHOD.
+
+ METHOD next.
+ mi_source->next( ).
+ ENDMETHOD.
+
+ METHOD refresh.
+ mi_source->clear( ).
+ mo_output->delete_text( ).
+ mo_console->delete_text( ).
+ ENDMETHOD. "refresh
+
+ METHOD pbo.
+ SET PF-STATUS '0100'.
+ SET TITLEBAR '0100' WITH app->mv_title.
+ app->first_output( ).
+ ENDMETHOD.
+
+ METHOD pai.
+ rd_flag = app->handle_user_command( id_code ).
+ ENDMETHOD.
+
+ METHOD free.
+ app->free_controls( ).
+ ENDMETHOD.
+
+
+ METHOD chat.
+ app = NEW #( ).
+ CALL SCREEN 100.
+ ENDMETHOD.
+
+ METHOD default_model.
+ SELECT provider_model FROM zllm_clnt_config UP TO 1 ROWS INTO @rd_Model.
+ ENDSELECT.
+ ENDMETHOD.
+
+ METHOD handle_user_command.
+ rd_flag = abap_false.
+
+ CASE ucomm.
+ WHEN 'EXECUTE'.
+ evaluate( ). " get_response( ).
+ WHEN 'CLEAR'.
+ refresh( ).
+ WHEN 'PREV'.
+ previous( ).
+ WHEN 'NEXT'.
+ next( ).
+
+ WHEN 'SM59'.
+ TRY.
+ CALL TRANSACTION 'SM59' WITH AUTHORITY-CHECK.
+ CATCH cx_sy_authorization_error INTO DATA(lx_error).
+ MESSAGE lx_error TYPE 'I' DISPLAY LIKE 'E'.
+ ENDTRY.
+ WHEN 'PROVIDERS'.
+ call_transaction( 'ZLLM_PROVIDER_CONFIG' ).
+
+ WHEN 'MODELS'.
+ call_transaction( 'ZLLM_CLIENT_CONFIG' ).
+
+ WHEN 'STATS'.
+ call_transaction( 'ZLLM_SYSTEM_CONF' ).
+
+ WHEN OTHERS.
+ RETURN.
+ ENDCASE.
+
+ rd_flag = abap_true.
+ ENDMETHOD.
+
+ METHOD call_transaction.
+ TRY.
+ CALL TRANSACTION id_transaction WITH AUTHORITY-CHECK.
+ CATCH cx_sy_authorization_error INTO DATA(lx_error).
+ MESSAGE lx_error TYPE 'I' DISPLAY LIKE 'E'.
+ ENDTRY.
+ ENDMETHOD.
+
+ METHOD evaluate.
+ DATA query TYPE string.
+ DATA response TYPE string.
+ DATA output TYPE string.
+ DATA lx_root TYPE REF TO cx_root.
+ TRY.
+ query = mi_source->to_string( ).
+
+ IF query IS INITIAL.
+ MESSAGE 'Please enter a message.'(003) TYPE 'I' DISPLAY LIKE 'W'.
+ RETURN.
+ ENDIF.
+
+ DATA(ld_start_time) = read_time( ).
+
+ DATA(client) = zcl_llm_factory=>get_client( model ).
+ DATA(resp) = client->execute( user_message = query ).
+
+ runtime = read_time( ) - ld_start_time.
+
+ IF resp-error-error_text IS NOT INITIAL.
+ mo_console->append_source( resp-error-error_text && |\n| ).
+ ENDIF.
+
+ response = resp-choice-message-content.
+
+ mi_source->push_text( ).
+ mi_source->update_status( |[ { runtime } µs ] { response }| ).
+
+ CATCH zcx_llm_authorization.
+ mo_console->append_source( 'Not authorized.'(005) && |\n| ).
+
+ CATCH cx_root INTO lx_root.
+ response = lx_root->get_text( ).
+ mi_source->update_status( response ).
+ ENDTRY.
+
+ mo_output->append_source( |{ query }\n=> { response }\n| ).
+ ENDMETHOD.
+
+ENDCLASS.
diff --git a/src/yy_llm_ide.prog.xml b/src/yy_llm_ide.prog.xml
new file mode 100644
index 0000000..1d0eca3
--- /dev/null
+++ b/src/yy_llm_ide.prog.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+ YY_LLM_IDE
+ I
+ K
+ E
+ X
+
+
+ -
+ R
+ Include YY_LLM_IDE
+ 18
+
+
+
+
+
diff --git a/src/zllm_chat_example.prog.abap b/src/zllm_chat_example.prog.abap
index 478fc38..3b20b8f 100644
--- a/src/zllm_chat_example.prog.abap
+++ b/src/zllm_chat_example.prog.abap
@@ -4,157 +4,13 @@
*&
*&---------------------------------------------------------------------*
REPORT zllm_chat_example.
-DATA model TYPE zllm_model.
-DATA user_message TYPE string.
-CLASS lcl_app DEFINITION.
- PUBLIC SECTION.
- METHODS display.
- METHODS handle_user_command IMPORTING ucomm TYPE sy-ucomm.
- METHODS initialize_text_editors.
+PARAMETERS model TYPE zllm_model MATCHCODE OBJECT zllm_model.
- PRIVATE SECTION.
- DATA: text_editor_input TYPE REF TO cl_gui_textedit,
- text_editor_output TYPE REF TO cl_gui_textedit,
- custom_container_in TYPE REF TO cl_gui_custom_container,
- custom_container_out TYPE REF TO cl_gui_custom_container.
-
-
- METHODS get_response.
- METHODS set_output_text IMPORTING text TYPE string.
- METHODS cleanup_controls.
-ENDCLASS.
-
-CLASS lcl_app IMPLEMENTATION.
- METHOD display.
- CALL SCREEN 100.
- ENDMETHOD.
-
- METHOD handle_user_command.
- CASE ucomm.
- WHEN 'SEND'.
- get_response( ).
- WHEN 'BACK' OR 'CANCEL' OR 'EXIT'. " Consistent handling
- cleanup_controls( ).
- LEAVE TO SCREEN 0. " Exit the program
- ENDCASE.
- ENDMETHOD.
-
- METHOD initialize_text_editors.
- IF text_editor_input IS NOT BOUND. " Only initialize if not already done
- custom_container_in = NEW #( container_name = 'INPUT_CONTAINER' ).
- text_editor_input = NEW #( parent = custom_container_in ).
-
- " Settings for input editor
- text_editor_input->set_toolbar_mode( cl_gui_textedit=>false ).
- text_editor_input->set_statusbar_mode( cl_gui_textedit=>false ).
- text_editor_input->set_wordwrap_behavior( wordwrap_mode = cl_gui_textedit=>wordwrap_at_fixed_position
- wordwrap_position = 100 ).
- ENDIF.
-
- IF text_editor_output IS NOT BOUND.
- custom_container_out = NEW #( container_name = 'OUTPUT_CONTAINER' ).
- text_editor_output = NEW #( parent = custom_container_out ).
-
- " Settings for output editor
- text_editor_output->set_toolbar_mode( cl_gui_textedit=>false ).
- text_editor_output->set_statusbar_mode( cl_gui_textedit=>false ).
- text_editor_output->set_wordwrap_behavior( wordwrap_mode = cl_gui_textedit=>wordwrap_at_fixed_position
- wordwrap_position = 100 ).
- text_editor_output->set_readonly_mode( 1 ). " Make output read-only
- ENDIF.
-
- " Flush operations so controls are sent to the frontend immediately!
- cl_gui_cfw=>flush( ).
- ENDMETHOD.
-
- METHOD get_response.
- " Error Handling first!
- IF model IS INITIAL.
- MESSAGE 'Please select a model.'(002) TYPE 'I' DISPLAY LIKE 'E'.
- RETURN.
- ENDIF.
-
- " Get user input text
- DATA texts TYPE STANDARD TABLE OF char255.
-
- text_editor_input->get_text_as_stream( IMPORTING text = texts ).
-
- user_message = concat_lines_of( table = texts
- sep = cl_abap_char_utilities=>cr_lf ).
-
- IF user_message IS INITIAL.
- MESSAGE 'Please enter a message.'(003) TYPE 'I' DISPLAY LIKE 'E'.
- RETURN.
- ENDIF.
-
- TRY.
- DATA(client) = zcl_llm_factory=>get_client( model ).
- DATA(response) = client->execute( user_message = user_message ).
- set_output_text( response-choice-message-content ).
-
- CATCH zcx_llm_authorization.
- MESSAGE 'Not authorized.'(005) TYPE 'I' DISPLAY LIKE 'E'.
- ENDTRY.
- ENDMETHOD.
-
- METHOD set_output_text.
- DATA texts TYPE STANDARD TABLE OF char255.
-
- " Convert the string to table of fixed-length strings
- DATA(remaining_text) = text.
- WHILE strlen( remaining_text ) > 0.
- DATA(line) = substring( val = remaining_text
- len = COND #(
- WHEN strlen( remaining_text ) > 255
- THEN 255
- ELSE strlen( remaining_text ) ) ).
- APPEND line TO texts.
- remaining_text = substring( val = remaining_text
- off = strlen( line )
- len = strlen( remaining_text ) - strlen( line ) ).
- ENDWHILE.
-
- text_editor_output->set_text_as_stream( texts ).
- cl_gui_cfw=>flush( ).
- ENDMETHOD.
-
- METHOD cleanup_controls.
- IF text_editor_input IS BOUND.
- text_editor_input->free( ).
- ENDIF.
- IF text_editor_output IS BOUND.
- text_editor_output->free( ).
- ENDIF.
-
- IF custom_container_in IS BOUND.
- custom_container_in->free( ).
- ENDIF.
- IF custom_container_out IS BOUND.
- custom_container_out->free( ).
- ENDIF.
- ENDMETHOD.
-ENDCLASS.
-
-DATA app TYPE REF TO lcl_app.
+INCLUDE yy_llm_ide.
INITIALIZATION.
- app = NEW #( ).
+ model = lcl_app=>default_model( ).
START-OF-SELECTION.
- app->display( ).
-
-*&---------------------------------------------------------------------*
-*& Module STATUS_0100 OUTPUT
-*&---------------------------------------------------------------------*
-MODULE status_0100 OUTPUT.
- SET PF-STATUS '0100'.
- SET TITLEBAR '0100'.
- app->initialize_text_editors( ).
-ENDMODULE.
-*&---------------------------------------------------------------------*
-*& Module USER_COMMAND_0100 INPUT
-*&---------------------------------------------------------------------*
-MODULE user_command_0100 INPUT.
- app->handle_user_command( sy-ucomm ).
-ENDMODULE.
+ lcl_app=>chat( ).
diff --git a/src/zllm_chat_example.prog.screen_0100.abap b/src/zllm_chat_example.prog.screen_0100.abap
index 0adce5b..ae683e2 100644
--- a/src/zllm_chat_example.prog.screen_0100.abap
+++ b/src/zllm_chat_example.prog.screen_0100.abap
@@ -2,4 +2,5 @@ PROCESS BEFORE OUTPUT.
MODULE status_0100.
PROCESS AFTER INPUT.
+ MODULE cancel_0100 AT EXIT-COMMAND.
MODULE user_command_0100.
diff --git a/src/zllm_chat_example.prog.xml b/src/zllm_chat_example.prog.xml
index 48dac03..099373a 100644
--- a/src/zllm_chat_example.prog.xml
+++ b/src/zllm_chat_example.prog.xml
@@ -19,7 +19,7 @@
N
0100
038
- 213
+ 214
@@ -78,23 +78,6 @@
X
ZLLM_MODEL
-
- SCREEN
- SCREEN
- PUSH
- SEND
- SEND___
- ICON_MAIL
- X
- 001
- 112
- 012
- 010
- 001
- SEND
- CHAR
- N
-
SCREEN
SCREEN
@@ -127,6 +110,7 @@
SCREEN
SCREEN
OKCODE
+ G_OK_CODE
____________________
020
020
@@ -140,7 +124,7 @@
000001
- 000001
+ 000003
000001
@@ -157,22 +141,86 @@
BACK
001
+ E
S
Back
CANCEL
001
+ E
S
Exit
+
+ CLEAR
+ 001
+ S
+ ICON_DELETE
+ @11@
+ Refresh
+ Refresh
+ Refresh
+ E
+
+
+ EVALUATE
+ 001
+ S
+ Evaluate
+ V
+
+
+ EXECUTE
+ 001
+ S
+ ICON_SYSTEM_PLAY
+ @I6@
+ Send
+ Evaluate
+ Evaluate
+
EXIT
001
+ E
S
ICON_CANCEL
@0W@
Cancel
+ A
+
+
+ MODELS
+ 001
+ S
+ Modell Configuration
+
+
+ NEXT
+ 001
+ S
+ ICON_ARROW_RIGHT
+ @9T@
+ Next
+ Next
+ Next query
+
+
+ PREV
+ 001
+ S
+ ICON_ARROW_LEFT
+ @9S@
+ Previous
+ Previous
+ Previous query
+
+
+ PROVIDERS
+ 001
+ S
+ Providers
SEND
@@ -181,13 +229,72 @@
SEND
S
+
+ SM59
+ 001
+ S
+ RFC Destinations
+
+
+ STATS
+ 001
+ S
+ Statistics / Logs
+
000001
01
F
- SEND
+ EVALUATE
+ 001
+
+
+ 000001
+ 02
+ S
+
+
+ 000001
+ 03
+ F
+ CLEAR
+ 001
+
+
+ 000001
+ 04
+ F
+ EXIT
+ 001
+
+
+ 000003
+ 01
+ F
+ SM59
+ 001
+
+
+ 000003
+ 02
+ F
+ PROVIDERS
+ 001
+
+
+ 000003
+ 03
+ F
+ MODELS
+ 001
+
+
+ 000003
+ 04
+ F
+ STATS
001
@@ -195,8 +302,19 @@
000001
S
- SEND
- S
+ User Interface
+ U
+
+
+ 000002
+ S
+ Modell
+ M
+
+
+ 000003
+ S
+ Customizing
@@ -205,7 +323,38 @@
01
000001
+
+ 000001
+ 02
+ 000003
+
+
+
+ 000001
+ 0001
+ 01
+ 08
+
+
+ 000001
+ 0001
+ 02
+ 13
+
+
+ 000001
+ 0001
+ 03
+ 14
+
+
+ 000001
+ 0001
+ 04
+ 16
+
+
000001
@@ -213,18 +362,42 @@
BACK
001
+
+ 000001
+ 08
+ EXECUTE
+ 001
+
000001
12
EXIT
001
+
+ 000001
+ 13
+ PREV
+ 001
+
+
+ 000001
+ 14
+ NEXT
+ 001
+
000001
15
CANCEL
001
+
+ 000001
+ 16
+ CLEAR
+ 001
+
@@ -235,14 +408,50 @@
0100
CANCEL
+
+ 0100
+ CLEAR
+
+
+ 0100
+ EVALUATE
+
+
+ 0100
+ EXECUTE
+
0100
EXIT
+
+ 0100
+ MODELS
+
+
+ 0100
+ NEXT
+
+
+ 0100
+ PREV
+
+
+ 0100
+ PROVIDERS
+
0100
SEND
+
+ 0100
+ SM59
+
+
+ 0100
+ STATS
+
@@ -268,7 +477,7 @@
0100
- Chat Example
+ Chat Example - Model &1
@@ -296,6 +505,13 @@
LLM Chat Example report
23
+ -
+ S
+ MODEL
+ .
+ 9
+ D
+