glaip-sdk 0.0.7__py3-none-any.whl → 0.0.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,198 @@
1
+ """prompt_toolkit integration helpers for the slash session.
2
+
3
+ Authors:
4
+ Raymond Christopher (raymond.christopher@gdplabs.id)
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from collections.abc import Iterable
10
+ from typing import TYPE_CHECKING, Any
11
+
12
+ _HAS_PROMPT_TOOLKIT = False
13
+
14
+ try: # pragma: no cover - optional dependency
15
+ from prompt_toolkit import PromptSession
16
+ from prompt_toolkit.completion import Completer, Completion
17
+ from prompt_toolkit.formatted_text import FormattedText
18
+ from prompt_toolkit.key_binding import KeyBindings
19
+ from prompt_toolkit.patch_stdout import patch_stdout
20
+ from prompt_toolkit.styles import Style
21
+
22
+ _HAS_PROMPT_TOOLKIT = True
23
+ except Exception: # pragma: no cover - optional dependency
24
+ PromptSession = None # type: ignore[assignment]
25
+ Completer = None # type: ignore[assignment]
26
+ Completion = None # type: ignore[assignment]
27
+ FormattedText = None # type: ignore[assignment]
28
+ KeyBindings = None # type: ignore[assignment]
29
+ Style = None # type: ignore[assignment]
30
+ patch_stdout = None # type: ignore[assignment]
31
+
32
+ if TYPE_CHECKING: # pragma: no cover - typing only
33
+ from .session import SlashSession
34
+
35
+
36
+ if _HAS_PROMPT_TOOLKIT:
37
+
38
+ class SlashCompleter(Completer):
39
+ """Provide slash command completions inside the prompt."""
40
+
41
+ def __init__(self, session: SlashSession) -> None:
42
+ self._session = session
43
+
44
+ def get_completions(
45
+ self,
46
+ document: Any,
47
+ _complete_event: Any, # type: ignore[no-any-return]
48
+ ) -> Iterable[Completion]: # pragma: no cover - UI
49
+ if Completion is None:
50
+ return
51
+
52
+ text = document.text_before_cursor or ""
53
+ if not text.startswith("/") or " " in text:
54
+ return
55
+
56
+ yield from _iter_command_completions(self._session, text)
57
+ yield from _iter_contextual_completions(self._session, text)
58
+
59
+ else: # pragma: no cover - fallback when prompt_toolkit is missing
60
+
61
+ class SlashCompleter: # type: ignore[too-many-ancestors]
62
+ def __init__(self, session: SlashSession) -> None: # noqa: D401 - stub
63
+ self._session = session
64
+
65
+
66
+ def setup_prompt_toolkit(
67
+ session: SlashSession,
68
+ *,
69
+ interactive: bool,
70
+ ) -> tuple[Any | None, Any | None]:
71
+ """Configure prompt_toolkit session and style for interactive mode."""
72
+
73
+ if not (interactive and _HAS_PROMPT_TOOLKIT):
74
+ return None, None
75
+
76
+ if PromptSession is None or Style is None:
77
+ return None, None
78
+
79
+ bindings = _create_key_bindings()
80
+
81
+ prompt_session = PromptSession(
82
+ completer=SlashCompleter(session),
83
+ complete_while_typing=True,
84
+ key_bindings=bindings,
85
+ )
86
+ prompt_style = Style.from_dict(
87
+ {
88
+ "prompt": "bg:#0f172a #facc15 bold",
89
+ "": "bg:#0f172a #e2e8f0",
90
+ "placeholder": "bg:#0f172a #94a3b8 italic",
91
+ }
92
+ )
93
+
94
+ return prompt_session, prompt_style
95
+
96
+
97
+ def _create_key_bindings() -> Any:
98
+ """Create prompt_toolkit key bindings for the command palette."""
99
+
100
+ if KeyBindings is None:
101
+ return None
102
+
103
+ bindings = KeyBindings()
104
+
105
+ def _refresh_completions(buffer: Any) -> None: # type: ignore[no-any-return]
106
+ text = buffer.document.text_before_cursor or ""
107
+ if text.startswith("/") and " " not in text:
108
+ buffer.start_completion(select_first=False)
109
+ elif buffer.complete_state is not None:
110
+ buffer.cancel_completion()
111
+
112
+ @bindings.add("/") # type: ignore[misc]
113
+ def _trigger_slash_completion(event: Any) -> None: # pragma: no cover - UI
114
+ buffer = event.app.current_buffer
115
+ buffer.insert_text("/")
116
+ _refresh_completions(buffer)
117
+
118
+ @bindings.add("backspace") # type: ignore[misc]
119
+ def _handle_backspace(event: Any) -> None: # pragma: no cover - UI
120
+ buffer = event.app.current_buffer
121
+ if buffer.document.cursor_position > 0:
122
+ buffer.delete_before_cursor()
123
+ _refresh_completions(buffer)
124
+
125
+ @bindings.add("c-h") # type: ignore[misc]
126
+ def _handle_ctrl_h(event: Any) -> None: # pragma: no cover - UI
127
+ buffer = event.app.current_buffer
128
+ if buffer.document.cursor_position > 0:
129
+ buffer.delete_before_cursor()
130
+ _refresh_completions(buffer)
131
+
132
+ return bindings
133
+
134
+
135
+ def _iter_command_completions(
136
+ session: SlashSession, text: str
137
+ ) -> Iterable[Completion]: # pragma: no cover - thin wrapper
138
+ prefix = text[1:]
139
+ seen: set[str] = set()
140
+
141
+ if (
142
+ session.get_contextual_commands()
143
+ and not session.should_include_global_commands()
144
+ ):
145
+ return []
146
+
147
+ commands = sorted(session._unique_commands.values(), key=lambda c: c.name)
148
+
149
+ for cmd in commands:
150
+ for alias in (cmd.name, *cmd.aliases):
151
+ if alias in seen or alias.startswith("?"):
152
+ continue
153
+ if prefix and not alias.startswith(prefix):
154
+ continue
155
+ seen.add(alias)
156
+ label = f"/{alias}"
157
+ yield Completion(
158
+ text=label,
159
+ start_position=-len(text),
160
+ display=label,
161
+ display_meta=cmd.help,
162
+ )
163
+
164
+
165
+ def _iter_contextual_completions(
166
+ session: SlashSession, text: str
167
+ ) -> Iterable[Completion]: # pragma: no cover - thin wrapper
168
+ prefix = text[1:]
169
+ seen: set[str] = set()
170
+
171
+ contextual_commands = sorted(
172
+ session.get_contextual_commands().items(), key=lambda item: item[0]
173
+ )
174
+
175
+ for alias, help_text in contextual_commands:
176
+ if alias in seen:
177
+ continue
178
+ if prefix and not alias.startswith(prefix):
179
+ continue
180
+ seen.add(alias)
181
+ label = f"/{alias}"
182
+ yield Completion(
183
+ text=label,
184
+ start_position=-len(text),
185
+ display=label,
186
+ display_meta=help_text,
187
+ )
188
+
189
+
190
+ __all__ = [
191
+ "SlashCompleter",
192
+ "setup_prompt_toolkit",
193
+ "FormattedText",
194
+ "patch_stdout",
195
+ "PromptSession",
196
+ "Style",
197
+ "_HAS_PROMPT_TOOLKIT",
198
+ ]