glaip-sdk 0.1.0__py3-none-any.whl → 0.6.10__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/__init__.py +5 -2
- glaip_sdk/_version.py +10 -3
- glaip_sdk/agents/__init__.py +27 -0
- glaip_sdk/agents/base.py +1191 -0
- glaip_sdk/branding.py +15 -6
- glaip_sdk/cli/account_store.py +540 -0
- glaip_sdk/cli/agent_config.py +2 -6
- glaip_sdk/cli/auth.py +265 -45
- glaip_sdk/cli/commands/__init__.py +2 -2
- glaip_sdk/cli/commands/accounts.py +746 -0
- glaip_sdk/cli/commands/agents.py +251 -173
- glaip_sdk/cli/commands/common_config.py +101 -0
- glaip_sdk/cli/commands/configure.py +735 -143
- glaip_sdk/cli/commands/mcps.py +266 -134
- glaip_sdk/cli/commands/models.py +13 -9
- glaip_sdk/cli/commands/tools.py +67 -88
- glaip_sdk/cli/commands/transcripts.py +755 -0
- glaip_sdk/cli/commands/update.py +3 -8
- glaip_sdk/cli/config.py +49 -7
- glaip_sdk/cli/constants.py +38 -0
- glaip_sdk/cli/context.py +8 -0
- glaip_sdk/cli/core/__init__.py +79 -0
- glaip_sdk/cli/core/context.py +124 -0
- glaip_sdk/cli/core/output.py +846 -0
- glaip_sdk/cli/core/prompting.py +649 -0
- glaip_sdk/cli/core/rendering.py +187 -0
- glaip_sdk/cli/display.py +45 -32
- glaip_sdk/cli/hints.py +57 -0
- glaip_sdk/cli/io.py +14 -17
- glaip_sdk/cli/main.py +232 -143
- glaip_sdk/cli/masking.py +21 -33
- glaip_sdk/cli/mcp_validators.py +5 -15
- glaip_sdk/cli/pager.py +12 -19
- glaip_sdk/cli/parsers/__init__.py +1 -3
- glaip_sdk/cli/parsers/json_input.py +11 -22
- glaip_sdk/cli/resolution.py +3 -9
- glaip_sdk/cli/rich_helpers.py +1 -3
- glaip_sdk/cli/slash/__init__.py +0 -9
- glaip_sdk/cli/slash/accounts_controller.py +578 -0
- glaip_sdk/cli/slash/accounts_shared.py +75 -0
- glaip_sdk/cli/slash/agent_session.py +65 -29
- glaip_sdk/cli/slash/prompt.py +24 -10
- glaip_sdk/cli/slash/remote_runs_controller.py +566 -0
- glaip_sdk/cli/slash/session.py +807 -225
- glaip_sdk/cli/slash/tui/__init__.py +9 -0
- glaip_sdk/cli/slash/tui/accounts.tcss +86 -0
- glaip_sdk/cli/slash/tui/accounts_app.py +876 -0
- glaip_sdk/cli/slash/tui/background_tasks.py +72 -0
- glaip_sdk/cli/slash/tui/loading.py +58 -0
- glaip_sdk/cli/slash/tui/remote_runs_app.py +628 -0
- glaip_sdk/cli/transcript/__init__.py +12 -52
- glaip_sdk/cli/transcript/cache.py +258 -60
- glaip_sdk/cli/transcript/capture.py +72 -21
- glaip_sdk/cli/transcript/history.py +815 -0
- glaip_sdk/cli/transcript/launcher.py +1 -3
- glaip_sdk/cli/transcript/viewer.py +79 -499
- glaip_sdk/cli/update_notifier.py +177 -24
- glaip_sdk/cli/utils.py +242 -1308
- glaip_sdk/cli/validators.py +16 -18
- glaip_sdk/client/__init__.py +2 -1
- glaip_sdk/client/_agent_payloads.py +53 -37
- glaip_sdk/client/agent_runs.py +147 -0
- glaip_sdk/client/agents.py +320 -92
- glaip_sdk/client/base.py +78 -35
- glaip_sdk/client/main.py +19 -10
- glaip_sdk/client/mcps.py +123 -15
- glaip_sdk/client/run_rendering.py +136 -101
- glaip_sdk/client/shared.py +21 -0
- glaip_sdk/client/tools.py +163 -34
- glaip_sdk/client/validators.py +20 -48
- glaip_sdk/config/constants.py +11 -0
- glaip_sdk/exceptions.py +1 -3
- glaip_sdk/mcps/__init__.py +21 -0
- glaip_sdk/mcps/base.py +345 -0
- glaip_sdk/models/__init__.py +90 -0
- glaip_sdk/models/agent.py +47 -0
- glaip_sdk/models/agent_runs.py +116 -0
- glaip_sdk/models/common.py +42 -0
- glaip_sdk/models/mcp.py +33 -0
- glaip_sdk/models/tool.py +33 -0
- glaip_sdk/payload_schemas/__init__.py +1 -13
- glaip_sdk/payload_schemas/agent.py +1 -3
- glaip_sdk/registry/__init__.py +55 -0
- glaip_sdk/registry/agent.py +164 -0
- glaip_sdk/registry/base.py +139 -0
- glaip_sdk/registry/mcp.py +253 -0
- glaip_sdk/registry/tool.py +232 -0
- glaip_sdk/rich_components.py +58 -2
- glaip_sdk/runner/__init__.py +59 -0
- glaip_sdk/runner/base.py +84 -0
- glaip_sdk/runner/deps.py +115 -0
- glaip_sdk/runner/langgraph.py +706 -0
- glaip_sdk/runner/mcp_adapter/__init__.py +13 -0
- glaip_sdk/runner/mcp_adapter/base_mcp_adapter.py +43 -0
- glaip_sdk/runner/mcp_adapter/langchain_mcp_adapter.py +257 -0
- glaip_sdk/runner/mcp_adapter/mcp_config_builder.py +95 -0
- glaip_sdk/runner/tool_adapter/__init__.py +18 -0
- glaip_sdk/runner/tool_adapter/base_tool_adapter.py +44 -0
- glaip_sdk/runner/tool_adapter/langchain_tool_adapter.py +219 -0
- glaip_sdk/tools/__init__.py +22 -0
- glaip_sdk/tools/base.py +435 -0
- glaip_sdk/utils/__init__.py +58 -12
- glaip_sdk/utils/a2a/__init__.py +34 -0
- glaip_sdk/utils/a2a/event_processor.py +188 -0
- glaip_sdk/utils/agent_config.py +4 -14
- glaip_sdk/utils/bundler.py +267 -0
- glaip_sdk/utils/client.py +111 -0
- glaip_sdk/utils/client_utils.py +46 -28
- glaip_sdk/utils/datetime_helpers.py +58 -0
- glaip_sdk/utils/discovery.py +78 -0
- glaip_sdk/utils/display.py +25 -21
- glaip_sdk/utils/export.py +143 -0
- glaip_sdk/utils/general.py +1 -36
- glaip_sdk/utils/import_export.py +15 -16
- glaip_sdk/utils/import_resolver.py +492 -0
- glaip_sdk/utils/instructions.py +101 -0
- glaip_sdk/utils/rendering/__init__.py +115 -1
- glaip_sdk/utils/rendering/formatting.py +7 -35
- glaip_sdk/utils/rendering/layout/__init__.py +64 -0
- glaip_sdk/utils/rendering/{renderer → layout}/panels.py +10 -3
- glaip_sdk/utils/rendering/{renderer → layout}/progress.py +73 -12
- glaip_sdk/utils/rendering/layout/summary.py +74 -0
- glaip_sdk/utils/rendering/layout/transcript.py +606 -0
- glaip_sdk/utils/rendering/models.py +3 -6
- glaip_sdk/utils/rendering/renderer/__init__.py +9 -49
- glaip_sdk/utils/rendering/renderer/base.py +258 -1577
- glaip_sdk/utils/rendering/renderer/config.py +1 -5
- glaip_sdk/utils/rendering/renderer/debug.py +30 -34
- glaip_sdk/utils/rendering/renderer/factory.py +138 -0
- glaip_sdk/utils/rendering/renderer/stream.py +10 -51
- glaip_sdk/utils/rendering/renderer/summary_window.py +79 -0
- glaip_sdk/utils/rendering/renderer/thinking.py +273 -0
- glaip_sdk/utils/rendering/renderer/toggle.py +1 -3
- glaip_sdk/utils/rendering/renderer/tool_panels.py +442 -0
- glaip_sdk/utils/rendering/renderer/transcript_mode.py +162 -0
- glaip_sdk/utils/rendering/state.py +204 -0
- glaip_sdk/utils/rendering/step_tree_state.py +1 -3
- glaip_sdk/utils/rendering/steps/__init__.py +34 -0
- glaip_sdk/utils/rendering/{steps.py → steps/event_processor.py} +76 -517
- glaip_sdk/utils/rendering/steps/format.py +176 -0
- glaip_sdk/utils/rendering/steps/manager.py +387 -0
- glaip_sdk/utils/rendering/timing.py +36 -0
- glaip_sdk/utils/rendering/viewer/__init__.py +21 -0
- glaip_sdk/utils/rendering/viewer/presenter.py +184 -0
- glaip_sdk/utils/resource_refs.py +29 -26
- glaip_sdk/utils/runtime_config.py +425 -0
- glaip_sdk/utils/serialization.py +32 -46
- glaip_sdk/utils/sync.py +142 -0
- glaip_sdk/utils/tool_detection.py +33 -0
- glaip_sdk/utils/validation.py +20 -28
- {glaip_sdk-0.1.0.dist-info → glaip_sdk-0.6.10.dist-info}/METADATA +42 -4
- glaip_sdk-0.6.10.dist-info/RECORD +159 -0
- {glaip_sdk-0.1.0.dist-info → glaip_sdk-0.6.10.dist-info}/WHEEL +1 -1
- glaip_sdk/models.py +0 -259
- glaip_sdk-0.1.0.dist-info/RECORD +0 -82
- {glaip_sdk-0.1.0.dist-info → glaip_sdk-0.6.10.dist-info}/entry_points.txt +0 -0
|
@@ -14,8 +14,10 @@ import click
|
|
|
14
14
|
from glaip_sdk.branding import ERROR_STYLE, HINT_PREFIX_STYLE
|
|
15
15
|
from glaip_sdk.cli.commands.agents import get as agents_get_command
|
|
16
16
|
from glaip_sdk.cli.commands.agents import run as agents_run_command
|
|
17
|
+
from glaip_sdk.cli.constants import DEFAULT_AGENT_INSTRUCTION_PREVIEW_LIMIT
|
|
18
|
+
from glaip_sdk.cli.hints import format_command_hint
|
|
17
19
|
from glaip_sdk.cli.slash.prompt import _HAS_PROMPT_TOOLKIT, FormattedText
|
|
18
|
-
from glaip_sdk.cli.utils import
|
|
20
|
+
from glaip_sdk.cli.utils import bind_slash_session_context
|
|
19
21
|
|
|
20
22
|
if TYPE_CHECKING: # pragma: no cover - type checking only
|
|
21
23
|
from glaip_sdk.cli.slash.session import SlashSession
|
|
@@ -36,19 +38,22 @@ class AgentRunSession:
|
|
|
36
38
|
self.console = session.console
|
|
37
39
|
self._agent_id = str(getattr(agent, "id", ""))
|
|
38
40
|
self._agent_name = getattr(agent, "name", "") or self._agent_id
|
|
39
|
-
self._prompt_placeholder: str =
|
|
41
|
+
self._prompt_placeholder: str = (
|
|
42
|
+
"Chat with this agent here; use / for shortcuts. "
|
|
43
|
+
"Alt+Enter inserts a newline. Ctrl+T opens the last transcript."
|
|
44
|
+
)
|
|
40
45
|
self._contextual_completion_help: dict[str, str] = {
|
|
41
|
-
"details": "Show this agent's
|
|
46
|
+
"details": "Show this agent's configuration (+ expands prompt).",
|
|
42
47
|
"help": "Display this context-aware menu.",
|
|
48
|
+
"runs": "✨ NEW · Browse remote run history for this agent.",
|
|
43
49
|
"exit": "Return to the command palette.",
|
|
44
50
|
"q": "Return to the command palette.",
|
|
45
51
|
}
|
|
52
|
+
self._instruction_preview_limit = DEFAULT_AGENT_INSTRUCTION_PREVIEW_LIMIT
|
|
46
53
|
|
|
47
54
|
def run(self) -> None:
|
|
48
55
|
"""Run the interactive agent session loop."""
|
|
49
|
-
self.session.set_contextual_commands(
|
|
50
|
-
self._contextual_completion_help, include_global=False
|
|
51
|
-
)
|
|
56
|
+
self.session.set_contextual_commands(self._contextual_completion_help, include_global=False)
|
|
52
57
|
previous_agent = getattr(self.session, "_current_agent", None)
|
|
53
58
|
self.session._current_agent = self.agent
|
|
54
59
|
clear_ready = getattr(self.session, "clear_agent_transcript_ready", None)
|
|
@@ -88,6 +93,7 @@ class AgentRunSession:
|
|
|
88
93
|
try:
|
|
89
94
|
|
|
90
95
|
def _prompt_message() -> Any:
|
|
96
|
+
"""Get formatted prompt message for agent session."""
|
|
91
97
|
prompt_prefix = f"{self._agent_name} ({self._agent_id}) "
|
|
92
98
|
|
|
93
99
|
# Use FormattedText if prompt_toolkit is available, otherwise use simple string
|
|
@@ -124,7 +130,7 @@ class AgentRunSession:
|
|
|
124
130
|
if raw in {"/exit", "/back", "/q"}:
|
|
125
131
|
return self._handle_exit_command()
|
|
126
132
|
|
|
127
|
-
if raw
|
|
133
|
+
if raw == "/details":
|
|
128
134
|
return self._handle_details_command(agent_id)
|
|
129
135
|
|
|
130
136
|
if raw in {"/help", "/?"}:
|
|
@@ -153,15 +159,59 @@ class AgentRunSession:
|
|
|
153
159
|
self.session.handle_command(raw, invoked_from_agent=True)
|
|
154
160
|
return not self.session._should_exit
|
|
155
161
|
|
|
156
|
-
def _show_details(self, agent_id: str) -> None:
|
|
162
|
+
def _show_details(self, agent_id: str, *, enable_prompt: bool = True) -> None:
|
|
163
|
+
"""Render the agent's configuration export inside the command palette."""
|
|
157
164
|
try:
|
|
158
|
-
self.session.ctx.invoke(
|
|
159
|
-
|
|
160
|
-
|
|
165
|
+
self.session.ctx.invoke(
|
|
166
|
+
agents_get_command,
|
|
167
|
+
agent_ref=agent_id,
|
|
168
|
+
instruction_preview=self._instruction_preview_limit,
|
|
161
169
|
)
|
|
170
|
+
if enable_prompt:
|
|
171
|
+
self._prompt_instruction_view_toggle(agent_id)
|
|
172
|
+
self.console.print(
|
|
173
|
+
f"[{HINT_PREFIX_STYLE}]Tip:[/] Continue the conversation in this prompt, or use "
|
|
174
|
+
f"{format_command_hint('/help') or '/help'} for shortcuts."
|
|
175
|
+
)
|
|
162
176
|
except click.ClickException as exc:
|
|
163
177
|
self.console.print(f"[{ERROR_STYLE}]{exc}[/]")
|
|
164
178
|
|
|
179
|
+
def _prompt_instruction_view_toggle(self, agent_id: str) -> None:
|
|
180
|
+
"""Offer a prompt to expand or collapse the instruction preview after details."""
|
|
181
|
+
if not getattr(self.console, "is_terminal", False):
|
|
182
|
+
return
|
|
183
|
+
|
|
184
|
+
while True:
|
|
185
|
+
mode = "expanded" if self._instruction_preview_limit == 0 else "trimmed"
|
|
186
|
+
self.console.print(f"[dim]Instruction view is {mode}. Press Ctrl+T to toggle, Enter to continue.[/dim]")
|
|
187
|
+
try:
|
|
188
|
+
ch = click.getchar()
|
|
189
|
+
except (EOFError, KeyboardInterrupt): # pragma: no cover - defensive guard
|
|
190
|
+
return
|
|
191
|
+
|
|
192
|
+
if not self._handle_instruction_toggle_input(agent_id, ch):
|
|
193
|
+
break
|
|
194
|
+
|
|
195
|
+
if self._instruction_preview_limit == 0:
|
|
196
|
+
self._instruction_preview_limit = DEFAULT_AGENT_INSTRUCTION_PREVIEW_LIMIT
|
|
197
|
+
self.console.print("")
|
|
198
|
+
|
|
199
|
+
def _handle_instruction_toggle_input(self, agent_id: str, ch: str) -> bool:
|
|
200
|
+
"""Process a single toggle keypress; return False when the loop should exit."""
|
|
201
|
+
if ch in {"\r", "\n"}:
|
|
202
|
+
return False
|
|
203
|
+
|
|
204
|
+
lowered = ch.lower()
|
|
205
|
+
if lowered == "t" or ch == "\x14": # support literal 't' or Ctrl+T
|
|
206
|
+
self._instruction_preview_limit = (
|
|
207
|
+
DEFAULT_AGENT_INSTRUCTION_PREVIEW_LIMIT if self._instruction_preview_limit == 0 else 0
|
|
208
|
+
)
|
|
209
|
+
self._show_details(agent_id, enable_prompt=False)
|
|
210
|
+
return True
|
|
211
|
+
|
|
212
|
+
# Ignore other keys and continue prompting.
|
|
213
|
+
return True
|
|
214
|
+
|
|
165
215
|
def _after_agent_run(self) -> None:
|
|
166
216
|
"""Handle transcript viewer behaviour after a successful run."""
|
|
167
217
|
payload, manifest = self.session._get_last_transcript()
|
|
@@ -173,9 +223,7 @@ class AgentRunSession:
|
|
|
173
223
|
mark_ready(self._agent_id, run_id)
|
|
174
224
|
if self._open_transcript_viewer():
|
|
175
225
|
return
|
|
176
|
-
self.console.print(
|
|
177
|
-
"[dim]Transcript viewer is unavailable in this environment.[/dim]"
|
|
178
|
-
)
|
|
226
|
+
self.console.print("[dim]Transcript viewer is unavailable in this environment.[/dim]")
|
|
179
227
|
|
|
180
228
|
def _transcript_matches(self, payload: Any, manifest: Any) -> bool:
|
|
181
229
|
"""Return True when the latest transcript belongs to this agent."""
|
|
@@ -197,9 +245,7 @@ class AgentRunSession:
|
|
|
197
245
|
self.session.console.clear()
|
|
198
246
|
except Exception: # pragma: no cover - defensive cleanup
|
|
199
247
|
pass
|
|
200
|
-
if
|
|
201
|
-
current_agent is not None
|
|
202
|
-
): # pragma: no cover - UI refresh best effort
|
|
248
|
+
if current_agent is not None: # pragma: no cover - UI refresh best effort
|
|
203
249
|
try:
|
|
204
250
|
self.session._render_header(current_agent, focus_agent=True)
|
|
205
251
|
except Exception: # pragma: no cover - defensive cleanup
|
|
@@ -211,21 +257,11 @@ class AgentRunSession:
|
|
|
211
257
|
@contextmanager
|
|
212
258
|
def _bind_session_context(self) -> Any:
|
|
213
259
|
"""Temporarily attach this slash session to the Click context."""
|
|
214
|
-
|
|
215
|
-
has_context = isinstance(ctx_obj, dict)
|
|
216
|
-
previous_session = ctx_obj.get("_slash_session") if has_context else None
|
|
217
|
-
if has_context:
|
|
218
|
-
ctx_obj["_slash_session"] = self.session
|
|
219
|
-
try:
|
|
260
|
+
with bind_slash_session_context(self.session.ctx, self.session):
|
|
220
261
|
yield
|
|
221
|
-
finally:
|
|
222
|
-
if has_context:
|
|
223
|
-
if previous_session is None:
|
|
224
|
-
ctx_obj.pop("_slash_session", None)
|
|
225
|
-
else:
|
|
226
|
-
ctx_obj["_slash_session"] = previous_session
|
|
227
262
|
|
|
228
263
|
def _run_agent(self, agent_id: str, message: str) -> None:
|
|
264
|
+
"""Execute the agents run command for the active agent."""
|
|
229
265
|
if not message:
|
|
230
266
|
return
|
|
231
267
|
|
glaip_sdk/cli/slash/prompt.py
CHANGED
|
@@ -123,6 +123,11 @@ def _create_key_bindings(_session: SlashSession) -> Any:
|
|
|
123
123
|
bindings = KeyBindings()
|
|
124
124
|
|
|
125
125
|
def _refresh_completions(buffer: Any) -> None: # type: ignore[no-any-return]
|
|
126
|
+
"""Refresh completions when slash command is typed.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
buffer: Prompt buffer instance.
|
|
130
|
+
"""
|
|
126
131
|
text = buffer.document.text_before_cursor or ""
|
|
127
132
|
if text.startswith("/") and " " not in text:
|
|
128
133
|
buffer.start_completion(select_first=False)
|
|
@@ -157,12 +162,24 @@ def _create_key_bindings(_session: SlashSession) -> Any:
|
|
|
157
162
|
if buffer.complete_state is not None:
|
|
158
163
|
buffer.cancel_completion()
|
|
159
164
|
|
|
165
|
+
@bindings.add("c-t") # type: ignore[misc]
|
|
166
|
+
def _handle_ctrl_t_key(event: Any) -> None: # vulture: ignore
|
|
167
|
+
"""Handle Ctrl+T key - open the transcript viewer (when available)."""
|
|
168
|
+
buffer = event.app.current_buffer
|
|
169
|
+
if buffer.complete_state is not None:
|
|
170
|
+
buffer.cancel_completion()
|
|
171
|
+
|
|
172
|
+
open_viewer = getattr(_session, "open_transcript_viewer", None)
|
|
173
|
+
if callable(open_viewer):
|
|
174
|
+
open_viewer(announce=True)
|
|
175
|
+
|
|
160
176
|
return bindings
|
|
161
177
|
|
|
162
178
|
|
|
163
179
|
def _iter_command_completions(
|
|
164
180
|
session: SlashSession, text: str
|
|
165
181
|
) -> Iterable[Completion]: # pragma: no cover - thin wrapper
|
|
182
|
+
"""Yield completions for global slash commands."""
|
|
166
183
|
prefix = text[1:]
|
|
167
184
|
seen: set[str] = set()
|
|
168
185
|
|
|
@@ -171,22 +188,20 @@ def _iter_command_completions(
|
|
|
171
188
|
return []
|
|
172
189
|
|
|
173
190
|
commands = sorted(session._unique_commands.values(), key=lambda c: c.name)
|
|
191
|
+
agent_context = bool(getattr(session, "_current_agent", None))
|
|
174
192
|
|
|
175
193
|
for cmd in commands:
|
|
194
|
+
if getattr(cmd, "agent_only", False) and not agent_context:
|
|
195
|
+
continue
|
|
176
196
|
yield from _generate_command_completions(cmd, prefix, text, seen)
|
|
177
197
|
|
|
178
198
|
|
|
179
199
|
def _should_include_commands(session: SlashSession) -> bool:
|
|
180
200
|
"""Check if commands should be included in completions."""
|
|
181
|
-
return not (
|
|
182
|
-
session.get_contextual_commands()
|
|
183
|
-
and not session.should_include_global_commands()
|
|
184
|
-
)
|
|
201
|
+
return not (session.get_contextual_commands() and not session.should_include_global_commands())
|
|
185
202
|
|
|
186
203
|
|
|
187
|
-
def _generate_command_completions(
|
|
188
|
-
cmd: Any, prefix: str, text: str, seen: set[str]
|
|
189
|
-
) -> Iterable[Completion]:
|
|
204
|
+
def _generate_command_completions(cmd: Any, prefix: str, text: str, seen: set[str]) -> Iterable[Completion]:
|
|
190
205
|
"""Generate completion items for a single command."""
|
|
191
206
|
for alias in (cmd.name, *cmd.aliases):
|
|
192
207
|
if alias in seen or alias.startswith("?"):
|
|
@@ -208,12 +223,11 @@ def _generate_command_completions(
|
|
|
208
223
|
def _iter_contextual_completions(
|
|
209
224
|
session: SlashSession, text: str
|
|
210
225
|
) -> Iterable[Completion]: # pragma: no cover - thin wrapper
|
|
226
|
+
"""Yield completions for context-specific slash commands."""
|
|
211
227
|
prefix = text[1:]
|
|
212
228
|
seen: set[str] = set()
|
|
213
229
|
|
|
214
|
-
contextual_commands = sorted(
|
|
215
|
-
session.get_contextual_commands().items(), key=lambda item: item[0]
|
|
216
|
-
)
|
|
230
|
+
contextual_commands = sorted(session.get_contextual_commands().items(), key=lambda item: item[0])
|
|
217
231
|
|
|
218
232
|
for alias, help_text in contextual_commands:
|
|
219
233
|
if alias in seen:
|