Skip to content

Commit ce30940

Browse files
authored
Backport PR ipython#14623: Multiline suggest in prompt_toolkit and LLM autocompletion (ipython#14705)
see ipython#14623 Minimal conflicts due to type informations.
2 parents 3c3c421 + e5d188c commit ce30940

File tree

3 files changed

+440
-18
lines changed

3 files changed

+440
-18
lines changed

IPython/terminal/interactiveshell.py

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@
2626
Any,
2727
validate,
2828
Float,
29+
DottedObjectName,
2930
)
31+
from traitlets.utils.importstring import import_item
32+
3033

3134
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
3235
from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
@@ -214,7 +217,9 @@ class TerminalInteractiveShell(InteractiveShell):
214217

215218
pt_app: UnionType[PromptSession, None] = None
216219
auto_suggest: UnionType[
217-
AutoSuggestFromHistory, NavigableAutoSuggestFromHistory, None
220+
AutoSuggestFromHistory,
221+
NavigableAutoSuggestFromHistory,
222+
None,
218223
] = None
219224
debugger_history = None
220225

@@ -421,6 +426,37 @@ def _displayhook_class_default(self):
421426
allow_none=True,
422427
).tag(config=True)
423428

429+
llm_provider_class = DottedObjectName(
430+
None,
431+
allow_none=True,
432+
help="""\
433+
Provisional:
434+
This is a provisinal API in IPython 8.32, before stabilisation
435+
in 9.0, it may change without warnings.
436+
437+
class to use for the `NavigableAutoSuggestFromHistory` to request
438+
completions from a LLM, this should inherit from
439+
`jupyter_ai_magics:BaseProvider` and implement
440+
`stream_inline_completions`
441+
""",
442+
).tag(config=True)
443+
444+
@observe("llm_provider_class")
445+
def _llm_provider_class_changed(self, change):
446+
provider_class = change.new
447+
if provider_class is not None:
448+
warn(
449+
"TerminalInteractiveShell.llm_provider_class is a provisional"
450+
" API as of IPython 8.32, and may change without warnings."
451+
)
452+
if isinstance(self.auto_suggest, NavigableAutoSuggestFromHistory):
453+
self.auto_suggest._llm_provider = provider_class()
454+
else:
455+
self.log.warn(
456+
"llm_provider_class only has effects when using"
457+
"`NavigableAutoSuggestFromHistory` as auto_suggest."
458+
)
459+
424460
def _set_autosuggestions(self, provider):
425461
# disconnect old handler
426462
if self.auto_suggest and isinstance(
@@ -432,7 +468,15 @@ def _set_autosuggestions(self, provider):
432468
elif provider == "AutoSuggestFromHistory":
433469
self.auto_suggest = AutoSuggestFromHistory()
434470
elif provider == "NavigableAutoSuggestFromHistory":
471+
# LLM stuff are all Provisional in 8.32
472+
if self.llm_provider_class:
473+
llm_provider_constructor = import_item(self.llm_provider_class)
474+
llm_provider = llm_provider_constructor()
475+
else:
476+
llm_provider = None
435477
self.auto_suggest = NavigableAutoSuggestFromHistory()
478+
# Provisinal in 8.32
479+
self.auto_suggest._llm_provider = llm_provider
436480
else:
437481
raise ValueError("No valid provider.")
438482
if self.pt_app:
@@ -815,7 +859,8 @@ def get_message():
815859
& ~IsDone()
816860
& Condition(
817861
lambda: isinstance(
818-
self.auto_suggest, NavigableAutoSuggestFromHistory
862+
self.auto_suggest,
863+
NavigableAutoSuggestFromHistory,
819864
)
820865
),
821866
),

0 commit comments

Comments
 (0)