@@ -280,6 +280,13 @@ Must be a positive integer."
280280 " Face for the user sent messages in chat."
281281 :group 'eca )
282282
283+ (defface eca-chat-rollback-face
284+ '((t (:inherit eca-chat-user-messages-face
285+ :weight bold
286+ :underline t )))
287+ " Face for the rollback button."
288+ :group 'eca )
289+
283290(defface eca-chat-system-messages-face
284291 '((t :inherit font-lock-builtin-face ))
285292 " Face for the system messages in chat."
@@ -629,6 +636,15 @@ Must be a positive integer."
629636 :params (list :chatId eca-chat--id))
630637 (eca-chat--set-chat-loading session nil )))
631638
639+ (defun eca-chat--rollback (session content-id )
640+ " Rollback chat messages for SESSION to before CONTENT-ID."
641+ (unless eca-chat--chat-loading
642+ (when (y-or-n-p " Do you want to really rollback the chat to before this message?" )
643+ (eca-api-request-sync session
644+ :method " chat/rollback"
645+ :params (list :chatId eca-chat--id
646+ :contentId content-id)))))
647+
632648(defun eca-chat--set-chat-loading (session loading )
633649 " Set the SESSION chat to a loading state if LOADING is non nil.
634650Otherwise to a not loading state."
@@ -1075,21 +1091,29 @@ space, tab, or newline."
10751091 (add-text-properties 0 (length first) properties first)
10761092 (concat first rest))))
10771093
1078- (defun eca-chat--add-expandable-content (id label content )
1094+ (defun eca-chat--add-expandable-content (id label content &optional icon-face )
10791095 " Add LABEL to the chat current position for ID as a interactive text.
10801096When expanded, shows CONTENT.
10811097Applies LABEL-FACE to label and CONTENT-FACE to content."
10821098 (save-excursion
10831099 (let* ((context-start (eca-chat--prompt-area-start-point))
1084- (start-point (1- context-start)))
1100+ (start-point (1- context-start))
1101+ (open-icon (if icon-face
1102+ (propertize eca-chat-expandable-block-open-symbol 'font-lock-face icon-face)
1103+ eca-chat-expandable-block-open-symbol))
1104+ (close-icon (if icon-face
1105+ (propertize eca-chat-expandable-block-close-symbol 'font-lock-face icon-face)
1106+ eca-chat-expandable-block-close-symbol)))
10851107 (goto-char start-point)
10861108 (unless (bolp ) (eca-chat--insert " \n " ))
10871109 (let ((ov-label (make-overlay (point ) (point ) (current-buffer ))))
10881110 (overlay-put ov-label 'eca-chat--expandable-content-id id)
1111+ (overlay-put ov-label 'eca-chat--expandable-content-open-icon open-icon)
1112+ (overlay-put ov-label 'eca-chat--expandable-content-close-icon close-icon)
10891113 (overlay-put ov-label 'eca-chat--expandable-content-toggle nil )
10901114 (eca-chat--insert (propertize (eca-chat--propertize-only-first-word label
10911115 'line-prefix (unless (string-empty-p content)
1092- eca-chat-expandable-block- open-symbol ))
1116+ open-icon ))
10931117 'keymap (let ((km (make-sparse-keymap )))
10941118 (define-key km (kbd " <mouse-1>" ) (lambda () (eca-chat--expandable-content-toggle id)))
10951119 (define-key km (kbd " <tab>" ) (lambda () (eca-chat--expandable-content-toggle id)))
@@ -1121,8 +1145,8 @@ Applies LABEL-FACE to label and CONTENT-FACE to content."
11211145 (eca-chat--insert (propertize (eca-chat--propertize-only-first-word label
11221146 'line-prefix (unless (string-empty-p new-content)
11231147 (if open?
1124- eca-chat-expandable-block -close-symbol
1125- eca-chat-expandable-block -open-symbol )))
1148+ ( overlay-get ov-label ' eca-chat-- expandable-content -close-icon )
1149+ ( overlay-get ov-label ' eca-chat-- expandable-content -open-icon ) )))
11261150 'help-echo " mouse-1 / RET / tab: expand/collapse" ))
11271151 (when open?
11281152 (if append-content?
@@ -1153,13 +1177,13 @@ If FORCE? decide to CLOSE? or not."
11531177 (progn
11541178 (put-text-property (point ) (line-end-position )
11551179 'line-prefix (unless empty-content?
1156- eca-chat-expandable-block -open-symbol ))
1180+ ( overlay-get ov-label ' eca-chat-- expandable-content -open-icon ) ))
11571181 (goto-char (1+ (line-end-position )))
11581182 (delete-region (overlay-start ov-content) (overlay-end ov-content))
11591183 (overlay-put ov-label 'eca-chat--expandable-content-toggle nil ))
11601184 (progn
11611185 (put-text-property (point ) (line-end-position )
1162- 'line-prefix eca-chat-expandable-block -close-symbol )
1186+ 'line-prefix ( overlay-get ov-label ' eca-chat-- expandable-content -close-icon ) )
11631187 (goto-char (overlay-start ov-content))
11641188 (eca-chat--insert content " \n " )
11651189 (overlay-put ov-label 'eca-chat--expandable-content-toggle t ))))
@@ -1854,6 +1878,7 @@ Append STATUS, TOOL-CALL-NEXT-LINE-SPACING and ROOTS"
18541878 (let* ((chat-id (plist-get params :chatId ))
18551879 (role (plist-get params :role ))
18561880 (content (plist-get params :content ))
1881+ (content-id (plist-get content :contentId ))
18571882 (roots (eca--session-workspace-folders session))
18581883 (tool-call-next-line-spacing (make-string (1+ (length eca-chat-expandable-block-open-symbol)) ?\s ))
18591884 (chat-buffer (eca-chat--get-chat-buffer session chat-id)))
@@ -1865,15 +1890,14 @@ Append STATUS, TOOL-CALL-NEXT-LINE-SPACING and ROOTS"
18651890 (when-let* ((text (plist-get content :text )))
18661891 (pcase role
18671892 (" user"
1868- (eca-chat--add-text-content
1869- (concat
1870- (unless eca-chat--empty " \n " )
1871- (propertize text
1872- 'font-lock-face 'eca-chat-user-messages-face
1873- 'line-prefix (propertize eca-chat-prompt-prefix
1874- 'font-lock-face 'eca-chat-user-messages-face )
1875- 'line-spacing 10 ))
1876- 'eca-chat--user-message-id eca-chat--last-request-id)
1893+ (eca-chat--add-expandable-content
1894+ content-id
1895+ (propertize (string-trim-right text) 'font-lock-face 'eca-chat-user-messages-face )
1896+ (eca-buttonize
1897+ eca-chat-mode-map
1898+ (propertize " Rollback chat to before this message" 'font-lock-face 'eca-chat-rollback-face )
1899+ (lambda () (eca-chat--rollback session content-id)))
1900+ 'eca-chat-user-messages-face )
18771901 (eca-chat--mark-header)
18781902 (font-lock-ensure ))
18791903 (" system"
@@ -1895,7 +1919,7 @@ Append STATUS, TOOL-CALL-NEXT-LINE-SPACING and ROOTS"
18951919 (" reasonStarted"
18961920 (let ((id (plist-get content :id ))
18971921 (label (propertize " Thinking..." 'font-lock-face 'eca-chat-reason-label-face )))
1898- (eca-chat--add-expandable-content id label " " )
1922+ (eca-chat--add-expandable-content id label " " 'eca-chat-reason-label-face )
18991923 (setq-local eca-chat--empty nil )))
19001924 (" reasonText"
19011925 (let ((id (plist-get content :id ))
@@ -1913,7 +1937,7 @@ Append STATUS, TOOL-CALL-NEXT-LINE-SPACING and ROOTS"
19131937 (let* ((id (plist-get content :id ))
19141938 (name (plist-get content :name ))
19151939 (label (propertize (format " Running hook '%s '... " name) 'font-lock-face 'eca-chat-hook-label-face )))
1916- (eca-chat--add-expandable-content id label " " )))
1940+ (eca-chat--add-expandable-content id label " " 'eca-chat-hook-label-face )))
19171941 (" hookActionFinished"
19181942 (let* ((id (plist-get content :id ))
19191943 (name (plist-get content :name ))
@@ -1958,7 +1982,8 @@ Append STATUS, TOOL-CALL-NEXT-LINE-SPACING and ROOTS"
19581982 (eca-chat--content-table
19591983 `((" Tool" . , name )
19601984 (" Server" . , server )
1961- (" Arguments" . , new-content )))))))))
1985+ (" Arguments" . , new-content )))
1986+ 'eca-chat-mcp-tool-call-label-face ))))))
19621987 (" toolCallRun"
19631988 (let* ((id (plist-get content :id ))
19641989 (args (plist-get content :arguments ))
@@ -2086,6 +2111,14 @@ Append STATUS, TOOL-CALL-NEXT-LINE-SPACING and ROOTS"
20862111 (setq-local eca-chat--session-cost (plist-get content :sessionCost )))
20872112 (_ nil )))))
20882113
2114+ (defun eca-chat-cleared (session params )
2115+ " Clear chat for SESSION and PARAMS requested by server."
2116+ (-let* ((chat-id (plist-get params :chatId ))
2117+ (messages? (plist-get params :messages ))
2118+ (chat-buffer (eca-chat--get-chat-buffer session chat-id)))
2119+ (eca-chat--with-current-buffer chat-buffer
2120+ (when messages?
2121+ (eca-chat--clear)))))
20892122
20902123(defun eca-chat-config-updated (session chat-config )
20912124 " Update chat based on the CHAT-CONFIG for SESSION."
0 commit comments