diff --git a/PacletInfo.wl b/PacletInfo.wl index 6cdb64e1..f16b7d1d 100644 --- a/PacletInfo.wl +++ b/PacletInfo.wl @@ -1,7 +1,7 @@ PacletObject[ <| "Name" -> "Wolfram/Chatbook", "PublisherID" -> "Wolfram", - "Version" -> "1.3.6", + "Version" -> "1.3.7", "WolframVersion" -> "13.3+", "Description" -> "Wolfram Notebooks + LLMs", "License" -> "MIT", diff --git a/Source/Chatbook/Actions.wl b/Source/Chatbook/Actions.wl index 625b84ee..4e011464 100644 --- a/Source/Chatbook/Actions.wl +++ b/Source/Chatbook/Actions.wl @@ -902,12 +902,7 @@ scrape // endDefinition; (*AttachCodeButtons*) AttachCodeButtons // beginDefinition; -AttachCodeButtons[ attached_, cell0_CellObject, string_, lang_ ] := - With[ { cell = parentCell @ cell0 }, - AttachCodeButtons[ attached, cell, string, lang ] /; chatCodeBlockQ @ cell - ]; - -AttachCodeButtons[ Dynamic[ attached_ ], cell_CellObject, string_, lang_ ] := ( +AttachCodeButtons[ Dynamic[ attached_ ], cell_CellObject? chatCodeBlockQ, string_, lang_ ] := ( attached = AttachCell[ cell, floatingButtonGrid[ attached, cell, lang ], @@ -918,15 +913,44 @@ AttachCodeButtons[ Dynamic[ attached_ ], cell_CellObject, string_, lang_ ] := ( ] ); +AttachCodeButtons[ attached_, cell_CellObject, string_, lang_ ] := Enclose[ + Catch @ Module[ { parent, evalCell, newParent }, + parent = parentCell @ cell; + + (* The parent cell is the chat code block as expected, so attach there *) + If[ chatCodeBlockQ @ parent, Throw @ AttachCodeButtons[ attached, parent, string, lang ] ]; + + (* Otherwise, we have an EvaluationCell[] failure, so try to recover by retrying EvaluationCell[] *) + evalCell = ConfirmMatch[ (FinishDynamic[ ]; EvaluationCell[ ]), _CellObject, "EvaluationCell" ]; + + (* The chat code block should be the parent of the current evaluation cell *) + newParent = ConfirmBy[ parentCell @ evalCell, chatCodeBlockQ, "ParentCell" ]; + + (* Finish attaching now that we have the correct cell *) + AttachCodeButtons[ attached, newParent, string, lang ] + ], + throwInternalFailure +]; + AttachCodeButtons // endDefinition; (* ::**************************************************************************************************************:: *) (* ::Subsection::Closed:: *) (*chatCodeBlockQ*) chatCodeBlockQ // beginDefinition; -chatCodeBlockQ[ cell_CellObject ] := chatCodeBlockQ[ cell, Developer`CellInformation @ cell ]; + +(* Many operations that return cell objects can return $Failed, but error handling should be done elsewhere: *) +chatCodeBlockQ[ $Failed ] := False; + +(* Cache the result, since we might be calling this multiple times on the same cell in AttachCodeButtons: *) +chatCodeBlockQ[ cell_CellObject ] := chatCodeBlockQ[ cell ] = chatCodeBlockQ[ cell, Developer`CellInformation @ cell ]; + +(* The expected style of a chat code block cell: *) chatCodeBlockQ[ cell_, KeyValuePattern[ "Style" -> "ChatCodeBlock" ] ] := True; + +(* Anything else means it's not a chat block: *) chatCodeBlockQ[ cell_, _ ] := False; + chatCodeBlockQ // endDefinition; (* ::**************************************************************************************************************:: *) diff --git a/Source/Chatbook/Formatting.wl b/Source/Chatbook/Formatting.wl index 73b47ebd..22eb9a25 100644 --- a/Source/Chatbook/Formatting.wl +++ b/Source/Chatbook/Formatting.wl @@ -1176,7 +1176,7 @@ inlineInteractiveCodeCell[ display_, string_, lang_ ] := ], TaggingRules -> <| "CellToStringType" -> "InlineInteractiveCodeCell", "CodeLanguage" -> lang |>, UnsavedVariables :> { $CellContext`attached, $CellContext`cell }, - Initialization :> { $CellContext`cell = EvaluationCell[ ] } + Initialization :> { $CellContext`cell = (FinishDynamic[ ]; EvaluationCell[ ]) } ]; inlineInteractiveCodeCell // endDefinition;