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.
- glaip_sdk/branding.py +3 -3
- glaip_sdk/cli/commands/agents.py +119 -12
- glaip_sdk/cli/display.py +4 -3
- glaip_sdk/cli/main.py +51 -5
- glaip_sdk/cli/resolution.py +17 -9
- glaip_sdk/cli/slash/__init__.py +25 -0
- glaip_sdk/cli/slash/agent_session.py +146 -0
- glaip_sdk/cli/slash/prompt.py +198 -0
- glaip_sdk/cli/slash/session.py +665 -0
- glaip_sdk/cli/utils.py +99 -5
- glaip_sdk/utils/rendering/renderer/base.py +19 -1
- glaip_sdk/utils/serialization.py +49 -17
- {glaip_sdk-0.0.7.dist-info → glaip_sdk-0.0.8.dist-info}/METADATA +1 -1
- {glaip_sdk-0.0.7.dist-info → glaip_sdk-0.0.8.dist-info}/RECORD +16 -12
- {glaip_sdk-0.0.7.dist-info → glaip_sdk-0.0.8.dist-info}/WHEEL +0 -0
- {glaip_sdk-0.0.7.dist-info → glaip_sdk-0.0.8.dist-info}/entry_points.txt +0 -0
|
@@ -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
|
+
]
|