glaip-sdk 0.6.19__py3-none-any.whl → 0.7.27__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/agents/base.py +283 -30
- glaip_sdk/agents/component.py +233 -0
- glaip_sdk/branding.py +113 -2
- glaip_sdk/cli/account_store.py +15 -0
- glaip_sdk/cli/auth.py +14 -8
- glaip_sdk/cli/commands/accounts.py +1 -1
- glaip_sdk/cli/commands/agents/__init__.py +116 -0
- glaip_sdk/cli/commands/agents/_common.py +562 -0
- glaip_sdk/cli/commands/agents/create.py +155 -0
- glaip_sdk/cli/commands/agents/delete.py +64 -0
- glaip_sdk/cli/commands/agents/get.py +89 -0
- glaip_sdk/cli/commands/agents/list.py +129 -0
- glaip_sdk/cli/commands/agents/run.py +264 -0
- glaip_sdk/cli/commands/agents/sync_langflow.py +72 -0
- glaip_sdk/cli/commands/agents/update.py +112 -0
- glaip_sdk/cli/commands/common_config.py +1 -1
- glaip_sdk/cli/commands/configure.py +1 -2
- glaip_sdk/cli/commands/mcps/__init__.py +94 -0
- glaip_sdk/cli/commands/mcps/_common.py +459 -0
- glaip_sdk/cli/commands/mcps/connect.py +82 -0
- glaip_sdk/cli/commands/mcps/create.py +152 -0
- glaip_sdk/cli/commands/mcps/delete.py +73 -0
- glaip_sdk/cli/commands/mcps/get.py +212 -0
- glaip_sdk/cli/commands/mcps/list.py +69 -0
- glaip_sdk/cli/commands/mcps/tools.py +235 -0
- glaip_sdk/cli/commands/mcps/update.py +190 -0
- glaip_sdk/cli/commands/models.py +2 -4
- glaip_sdk/cli/commands/shared/__init__.py +21 -0
- glaip_sdk/cli/commands/shared/formatters.py +91 -0
- glaip_sdk/cli/commands/tools/__init__.py +69 -0
- glaip_sdk/cli/commands/tools/_common.py +80 -0
- glaip_sdk/cli/commands/tools/create.py +228 -0
- glaip_sdk/cli/commands/tools/delete.py +61 -0
- glaip_sdk/cli/commands/tools/get.py +103 -0
- glaip_sdk/cli/commands/tools/list.py +69 -0
- glaip_sdk/cli/commands/tools/script.py +49 -0
- glaip_sdk/cli/commands/tools/update.py +102 -0
- glaip_sdk/cli/commands/transcripts/__init__.py +90 -0
- glaip_sdk/cli/commands/transcripts/_common.py +9 -0
- glaip_sdk/cli/commands/transcripts/clear.py +5 -0
- glaip_sdk/cli/commands/transcripts/detail.py +5 -0
- glaip_sdk/cli/commands/{transcripts.py → transcripts_original.py} +2 -1
- glaip_sdk/cli/commands/update.py +163 -17
- glaip_sdk/cli/config.py +1 -0
- glaip_sdk/cli/entrypoint.py +20 -0
- glaip_sdk/cli/main.py +112 -35
- glaip_sdk/cli/pager.py +3 -3
- glaip_sdk/cli/resolution.py +2 -1
- glaip_sdk/cli/slash/accounts_controller.py +3 -1
- glaip_sdk/cli/slash/agent_session.py +1 -1
- glaip_sdk/cli/slash/remote_runs_controller.py +3 -1
- glaip_sdk/cli/slash/session.py +343 -20
- glaip_sdk/cli/slash/tui/__init__.py +29 -1
- glaip_sdk/cli/slash/tui/accounts.tcss +97 -6
- glaip_sdk/cli/slash/tui/accounts_app.py +1117 -126
- glaip_sdk/cli/slash/tui/clipboard.py +316 -0
- glaip_sdk/cli/slash/tui/context.py +92 -0
- glaip_sdk/cli/slash/tui/indicators.py +341 -0
- glaip_sdk/cli/slash/tui/keybind_registry.py +235 -0
- glaip_sdk/cli/slash/tui/layouts/__init__.py +14 -0
- glaip_sdk/cli/slash/tui/layouts/harlequin.py +184 -0
- glaip_sdk/cli/slash/tui/loading.py +43 -21
- glaip_sdk/cli/slash/tui/remote_runs_app.py +178 -20
- glaip_sdk/cli/slash/tui/terminal.py +407 -0
- glaip_sdk/cli/slash/tui/theme/__init__.py +15 -0
- glaip_sdk/cli/slash/tui/theme/catalog.py +79 -0
- glaip_sdk/cli/slash/tui/theme/manager.py +112 -0
- glaip_sdk/cli/slash/tui/theme/tokens.py +55 -0
- glaip_sdk/cli/slash/tui/toast.py +388 -0
- glaip_sdk/cli/transcript/history.py +1 -1
- glaip_sdk/cli/transcript/viewer.py +1 -1
- glaip_sdk/cli/tui_settings.py +125 -0
- glaip_sdk/cli/update_notifier.py +215 -7
- glaip_sdk/cli/validators.py +1 -1
- glaip_sdk/client/__init__.py +2 -1
- glaip_sdk/client/_schedule_payloads.py +89 -0
- glaip_sdk/client/agents.py +293 -17
- glaip_sdk/client/base.py +25 -0
- glaip_sdk/client/hitl.py +136 -0
- glaip_sdk/client/main.py +7 -5
- glaip_sdk/client/mcps.py +44 -13
- glaip_sdk/client/payloads/agent/__init__.py +23 -0
- glaip_sdk/client/{_agent_payloads.py → payloads/agent/requests.py} +28 -48
- glaip_sdk/client/payloads/agent/responses.py +43 -0
- glaip_sdk/client/run_rendering.py +109 -30
- glaip_sdk/client/schedules.py +439 -0
- glaip_sdk/client/tools.py +52 -23
- glaip_sdk/config/constants.py +22 -2
- glaip_sdk/guardrails/__init__.py +80 -0
- glaip_sdk/guardrails/serializer.py +91 -0
- glaip_sdk/hitl/__init__.py +35 -2
- glaip_sdk/hitl/base.py +64 -0
- glaip_sdk/hitl/callback.py +43 -0
- glaip_sdk/hitl/local.py +1 -31
- glaip_sdk/hitl/remote.py +523 -0
- glaip_sdk/models/__init__.py +47 -1
- glaip_sdk/models/_provider_mappings.py +101 -0
- glaip_sdk/models/_validation.py +97 -0
- glaip_sdk/models/agent.py +2 -1
- glaip_sdk/models/agent_runs.py +2 -1
- glaip_sdk/models/constants.py +141 -0
- glaip_sdk/models/model.py +170 -0
- glaip_sdk/models/schedule.py +224 -0
- glaip_sdk/payload_schemas/agent.py +1 -0
- glaip_sdk/payload_schemas/guardrails.py +34 -0
- glaip_sdk/ptc.py +145 -0
- glaip_sdk/registry/tool.py +270 -57
- glaip_sdk/runner/__init__.py +20 -3
- glaip_sdk/runner/deps.py +4 -1
- glaip_sdk/runner/langgraph.py +251 -27
- glaip_sdk/runner/logging_config.py +77 -0
- glaip_sdk/runner/mcp_adapter/mcp_config_builder.py +30 -9
- glaip_sdk/runner/ptc_adapter.py +98 -0
- glaip_sdk/runner/tool_adapter/langchain_tool_adapter.py +25 -2
- glaip_sdk/schedules/__init__.py +22 -0
- glaip_sdk/schedules/base.py +291 -0
- glaip_sdk/tools/base.py +67 -14
- glaip_sdk/utils/__init__.py +1 -0
- glaip_sdk/utils/agent_config.py +8 -2
- glaip_sdk/utils/bundler.py +138 -2
- glaip_sdk/utils/import_resolver.py +427 -49
- glaip_sdk/utils/runtime_config.py +3 -2
- glaip_sdk/utils/sync.py +31 -11
- glaip_sdk/utils/tool_detection.py +274 -6
- {glaip_sdk-0.6.19.dist-info → glaip_sdk-0.7.27.dist-info}/METADATA +22 -8
- glaip_sdk-0.7.27.dist-info/RECORD +227 -0
- {glaip_sdk-0.6.19.dist-info → glaip_sdk-0.7.27.dist-info}/WHEEL +1 -1
- glaip_sdk-0.7.27.dist-info/entry_points.txt +2 -0
- glaip_sdk/cli/commands/agents.py +0 -1509
- glaip_sdk/cli/commands/mcps.py +0 -1356
- glaip_sdk/cli/commands/tools.py +0 -576
- glaip_sdk/cli/utils.py +0 -263
- glaip_sdk-0.6.19.dist-info/RECORD +0 -163
- glaip_sdk-0.6.19.dist-info/entry_points.txt +0 -2
- {glaip_sdk-0.6.19.dist-info → glaip_sdk-0.7.27.dist-info}/top_level.txt +0 -0
glaip_sdk/cli/commands/update.py
CHANGED
|
@@ -6,9 +6,12 @@ Author:
|
|
|
6
6
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
|
+
import importlib.util
|
|
10
|
+
import os
|
|
9
11
|
import subprocess
|
|
10
12
|
import sys
|
|
11
13
|
from collections.abc import Sequence
|
|
14
|
+
from pathlib import Path
|
|
12
15
|
|
|
13
16
|
import click
|
|
14
17
|
from rich.console import Console
|
|
@@ -18,19 +21,132 @@ from glaip_sdk.branding import ACCENT_STYLE, ERROR_STYLE, INFO_STYLE, SUCCESS_ST
|
|
|
18
21
|
PACKAGE_NAME = "glaip-sdk"
|
|
19
22
|
|
|
20
23
|
|
|
21
|
-
def
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
def _is_uv_managed_environment() -> bool:
|
|
25
|
+
"""Check if running in a uv-managed tool environment.
|
|
26
|
+
|
|
27
|
+
Uses a path-based heuristic against sys.executable, sys.prefix, and UV_TOOL_DIR
|
|
28
|
+
or UV_TOOL_BIN to detect a case-insensitive "uv/tools" segment. Update if uv
|
|
29
|
+
changes its layout.
|
|
30
|
+
"""
|
|
31
|
+
if _has_uv_tool_path(sys.executable):
|
|
32
|
+
return True
|
|
33
|
+
if _has_uv_tool_path(sys.prefix):
|
|
34
|
+
return True
|
|
35
|
+
uv_tool_dir = os.environ.get("UV_TOOL_DIR") or os.environ.get("UV_TOOL_BIN")
|
|
36
|
+
if uv_tool_dir and _has_uv_tool_path(uv_tool_dir):
|
|
37
|
+
return True
|
|
38
|
+
return False
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _has_uv_tool_path(path: str) -> bool:
|
|
42
|
+
"""Return True when a path contains a case-insensitive uv/tools segment."""
|
|
43
|
+
parts = [part.lower() for part in Path(path).parts]
|
|
44
|
+
for idx, part in enumerate(parts[:-1]):
|
|
45
|
+
if part == "uv" and parts[idx + 1] == "tools":
|
|
46
|
+
return True
|
|
47
|
+
return False
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _is_pip_available() -> bool:
|
|
51
|
+
"""Return True when pip can be imported in the current interpreter."""
|
|
52
|
+
return importlib.util.find_spec("pip") is not None
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _build_missing_pip_guidance(
|
|
56
|
+
*,
|
|
57
|
+
include_prerelease: bool,
|
|
58
|
+
package_name: str = PACKAGE_NAME,
|
|
59
|
+
force_reinstall: bool = False,
|
|
60
|
+
) -> tuple[str, str]:
|
|
61
|
+
"""Return error and troubleshooting guidance when pip is unavailable."""
|
|
62
|
+
manual_cmd = _build_manual_upgrade_command(
|
|
63
|
+
include_prerelease,
|
|
64
|
+
package_name=package_name,
|
|
65
|
+
is_uv=True,
|
|
66
|
+
force_reinstall=force_reinstall,
|
|
67
|
+
)
|
|
68
|
+
error_detail = "pip is not available in this environment."
|
|
69
|
+
troubleshooting = (
|
|
70
|
+
"💡 Troubleshooting:\n"
|
|
71
|
+
f" • If you installed via uv tool, run: {manual_cmd}\n"
|
|
72
|
+
" • Otherwise install pip: python -m ensurepip"
|
|
73
|
+
)
|
|
74
|
+
return error_detail, troubleshooting
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _build_command_parts(
|
|
78
|
+
*,
|
|
79
|
+
package_name: str = PACKAGE_NAME,
|
|
80
|
+
is_uv: bool | None = None,
|
|
81
|
+
force_reinstall: bool = False,
|
|
82
|
+
include_prerelease: bool = False,
|
|
83
|
+
) -> tuple[list[str], str]:
|
|
84
|
+
"""Build the common parts of upgrade commands.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
Tuple of (command parts list, force_reinstall flag name).
|
|
88
|
+
For uv: (["uv", "tool", "install", "--upgrade", package_name], "--reinstall")
|
|
89
|
+
For pip: (["pip", "install", "--upgrade", package_name], "--force-reinstall")
|
|
90
|
+
"""
|
|
91
|
+
if is_uv is None:
|
|
92
|
+
is_uv = _is_uv_managed_environment()
|
|
93
|
+
|
|
94
|
+
if is_uv:
|
|
95
|
+
command = ["uv", "tool", "install", "--upgrade", package_name]
|
|
96
|
+
reinstall_flag = "--reinstall"
|
|
97
|
+
else:
|
|
98
|
+
command = ["pip", "install", "--upgrade", package_name]
|
|
99
|
+
reinstall_flag = "--force-reinstall"
|
|
100
|
+
|
|
101
|
+
if force_reinstall:
|
|
102
|
+
command.insert(-1, reinstall_flag)
|
|
103
|
+
|
|
31
104
|
if include_prerelease:
|
|
32
105
|
command.append("--pre")
|
|
33
|
-
|
|
106
|
+
|
|
107
|
+
return command, reinstall_flag
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _build_upgrade_command(
|
|
111
|
+
include_prerelease: bool,
|
|
112
|
+
*,
|
|
113
|
+
package_name: str = PACKAGE_NAME,
|
|
114
|
+
is_uv: bool | None = None,
|
|
115
|
+
force_reinstall: bool = False,
|
|
116
|
+
) -> Sequence[str]:
|
|
117
|
+
"""Return the command used to upgrade the SDK (pip or uv tool install)."""
|
|
118
|
+
if is_uv is None:
|
|
119
|
+
is_uv = _is_uv_managed_environment()
|
|
120
|
+
|
|
121
|
+
command_parts, _ = _build_command_parts(
|
|
122
|
+
package_name=package_name,
|
|
123
|
+
is_uv=is_uv,
|
|
124
|
+
force_reinstall=force_reinstall,
|
|
125
|
+
include_prerelease=include_prerelease,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
# For pip, prepend sys.executable and -m
|
|
129
|
+
if not is_uv:
|
|
130
|
+
command_parts = [sys.executable, "-m"] + command_parts
|
|
131
|
+
|
|
132
|
+
return command_parts
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _build_manual_upgrade_command(
|
|
136
|
+
include_prerelease: bool,
|
|
137
|
+
*,
|
|
138
|
+
package_name: str = PACKAGE_NAME,
|
|
139
|
+
is_uv: bool | None = None,
|
|
140
|
+
force_reinstall: bool = False,
|
|
141
|
+
) -> str:
|
|
142
|
+
"""Return a manual upgrade command string matching the active environment."""
|
|
143
|
+
command_parts, _ = _build_command_parts(
|
|
144
|
+
package_name=package_name,
|
|
145
|
+
is_uv=is_uv,
|
|
146
|
+
force_reinstall=force_reinstall,
|
|
147
|
+
include_prerelease=include_prerelease,
|
|
148
|
+
)
|
|
149
|
+
return " ".join(command_parts)
|
|
34
150
|
|
|
35
151
|
|
|
36
152
|
@click.command(name="update")
|
|
@@ -40,22 +156,52 @@ def _build_upgrade_command(include_prerelease: bool) -> Sequence[str]:
|
|
|
40
156
|
is_flag=True,
|
|
41
157
|
help="Include pre-release versions when upgrading.",
|
|
42
158
|
)
|
|
43
|
-
|
|
44
|
-
""
|
|
159
|
+
@click.option(
|
|
160
|
+
"--reinstall",
|
|
161
|
+
"force_reinstall",
|
|
162
|
+
is_flag=True,
|
|
163
|
+
help="Force reinstall even if already up-to-date.",
|
|
164
|
+
)
|
|
165
|
+
def update_command(include_prerelease: bool, force_reinstall: bool) -> None:
|
|
166
|
+
"""Upgrade the glaip-sdk package using pip or uv tool install."""
|
|
45
167
|
console = Console()
|
|
46
|
-
|
|
168
|
+
# Call _is_uv_managed_environment() once and pass explicitly to avoid redundant calls
|
|
169
|
+
is_uv = _is_uv_managed_environment()
|
|
170
|
+
if not is_uv and not _is_pip_available():
|
|
171
|
+
error_detail, troubleshooting = _build_missing_pip_guidance(
|
|
172
|
+
include_prerelease=include_prerelease,
|
|
173
|
+
force_reinstall=force_reinstall,
|
|
174
|
+
)
|
|
175
|
+
raise click.ClickException(f"{error_detail}\n{troubleshooting}")
|
|
176
|
+
upgrade_cmd = _build_upgrade_command(
|
|
177
|
+
include_prerelease,
|
|
178
|
+
is_uv=is_uv,
|
|
179
|
+
force_reinstall=force_reinstall,
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
# Determine the appropriate manual command for error messages
|
|
183
|
+
manual_cmd = _build_manual_upgrade_command(
|
|
184
|
+
include_prerelease,
|
|
185
|
+
is_uv=is_uv,
|
|
186
|
+
force_reinstall=force_reinstall,
|
|
187
|
+
)
|
|
188
|
+
|
|
47
189
|
console.print(f"[{ACCENT_STYLE}]Upgrading {PACKAGE_NAME} using[/] [{INFO_STYLE}]{' '.join(upgrade_cmd)}[/]")
|
|
48
190
|
|
|
49
191
|
try:
|
|
50
192
|
subprocess.run(upgrade_cmd, check=True)
|
|
51
193
|
except FileNotFoundError as exc:
|
|
194
|
+
if is_uv:
|
|
195
|
+
raise click.ClickException(
|
|
196
|
+
f"Unable to locate uv executable. Please ensure uv is installed and on your PATH.\n"
|
|
197
|
+
f"Install uv: curl -LsSf https://astral.sh/uv/install.sh | sh\n"
|
|
198
|
+
f"Or run manually: {manual_cmd}"
|
|
199
|
+
) from exc
|
|
52
200
|
raise click.ClickException(
|
|
53
201
|
"Unable to locate Python executable to run pip. Please ensure Python is installed and try again."
|
|
54
202
|
) from exc
|
|
55
203
|
except subprocess.CalledProcessError as exc:
|
|
56
|
-
console.print(
|
|
57
|
-
f"[{ERROR_STYLE}]Automatic upgrade failed.[/] Please run `pip install -U {PACKAGE_NAME}` manually."
|
|
58
|
-
)
|
|
204
|
+
console.print(f"[{ERROR_STYLE}]Automatic upgrade failed.[/] Please run `{manual_cmd}` manually.")
|
|
59
205
|
raise click.ClickException("Automatic upgrade failed.") from exc
|
|
60
206
|
|
|
61
207
|
console.print(f"[{SUCCESS_STYLE}]✅ {PACKAGE_NAME} upgraded successfully.[/]")
|
glaip_sdk/cli/config.py
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""Entry point wrapper for early logging configuration.
|
|
2
|
+
|
|
3
|
+
This must be imported BEFORE glaip_sdk.cli.main to catch import-time warnings.
|
|
4
|
+
|
|
5
|
+
Authors:
|
|
6
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
# Configure logging BEFORE importing anything else
|
|
12
|
+
from glaip_sdk.runner.logging_config import setup_cli_logging
|
|
13
|
+
|
|
14
|
+
setup_cli_logging()
|
|
15
|
+
|
|
16
|
+
# Now import and run CLI
|
|
17
|
+
from glaip_sdk.cli import main # noqa: E402
|
|
18
|
+
|
|
19
|
+
if __name__ == "__main__":
|
|
20
|
+
sys.exit(main()) # pylint: disable=no-value-for-parameter
|
glaip_sdk/cli/main.py
CHANGED
|
@@ -35,18 +35,29 @@ from glaip_sdk.cli.commands.mcps import mcps_group
|
|
|
35
35
|
from glaip_sdk.cli.commands.models import models_group
|
|
36
36
|
from glaip_sdk.cli.commands.tools import tools_group
|
|
37
37
|
from glaip_sdk.cli.commands.transcripts import transcripts_group
|
|
38
|
-
from glaip_sdk.cli.commands.update import
|
|
38
|
+
from glaip_sdk.cli.commands.update import (
|
|
39
|
+
_build_missing_pip_guidance,
|
|
40
|
+
_build_manual_upgrade_command,
|
|
41
|
+
_build_upgrade_command,
|
|
42
|
+
_is_pip_available,
|
|
43
|
+
_is_uv_managed_environment,
|
|
44
|
+
update_command,
|
|
45
|
+
)
|
|
39
46
|
from glaip_sdk.cli.config import load_config
|
|
40
47
|
from glaip_sdk.cli.hints import in_slash_mode
|
|
48
|
+
from glaip_sdk.cli.core.output import format_size, sdk_version
|
|
49
|
+
from glaip_sdk.cli.core.rendering import spinner_context, update_spinner
|
|
41
50
|
from glaip_sdk.cli.transcript import get_transcript_cache_stats
|
|
42
51
|
from glaip_sdk.cli.update_notifier import maybe_notify_update
|
|
43
|
-
from glaip_sdk.cli.utils import format_size, sdk_version, spinner_context, update_spinner
|
|
44
52
|
from glaip_sdk.config.constants import (
|
|
45
53
|
DEFAULT_AGENT_RUN_TIMEOUT,
|
|
46
54
|
)
|
|
47
55
|
from glaip_sdk.icons import ICON_AGENT
|
|
48
56
|
from glaip_sdk.rich_components import AIPPanel, AIPTable
|
|
49
57
|
|
|
58
|
+
# Constants
|
|
59
|
+
UPDATE_ERROR_TITLE = "❌ Update Error"
|
|
60
|
+
|
|
50
61
|
Client: type[Any] | None = None
|
|
51
62
|
|
|
52
63
|
|
|
@@ -62,6 +73,12 @@ def _resolve_client_class() -> type[Any]:
|
|
|
62
73
|
|
|
63
74
|
def _suppress_chatty_loggers() -> None:
|
|
64
75
|
"""Silence noisy SDK/httpx logs for CLI output."""
|
|
76
|
+
# Ensure CLI logging is configured (idempotent)
|
|
77
|
+
from glaip_sdk.runner.logging_config import setup_cli_logging # noqa: PLC0415
|
|
78
|
+
|
|
79
|
+
setup_cli_logging()
|
|
80
|
+
|
|
81
|
+
# Also suppress SDK-specific loggers
|
|
65
82
|
noisy_loggers = [
|
|
66
83
|
"glaip_sdk.client",
|
|
67
84
|
"httpx",
|
|
@@ -237,26 +254,40 @@ def _load_and_merge_config(ctx: click.Context) -> dict:
|
|
|
237
254
|
|
|
238
255
|
def _validate_config_and_show_error(config: dict, console: Console) -> None:
|
|
239
256
|
"""Validate configuration and show error if incomplete."""
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
257
|
+
if config.get("api_url") and config.get("api_key"):
|
|
258
|
+
return
|
|
259
|
+
|
|
260
|
+
# Best effort: avoid failing validation due to config I/O issues.
|
|
261
|
+
has_accounts = True
|
|
262
|
+
logger = logging.getLogger(__name__)
|
|
263
|
+
try:
|
|
264
|
+
store = get_account_store()
|
|
265
|
+
try:
|
|
266
|
+
has_accounts = bool(store.list_accounts())
|
|
267
|
+
except Exception:
|
|
268
|
+
logger.warning("Failed to list accounts from account store.", exc_info=True)
|
|
269
|
+
has_accounts = True
|
|
270
|
+
except Exception:
|
|
271
|
+
logger.warning("Failed to initialize account store.", exc_info=True)
|
|
272
|
+
has_accounts = True
|
|
273
|
+
|
|
274
|
+
no_accounts_hint = "" if has_accounts else "\n • No accounts found; create one now to continue"
|
|
275
|
+
console.print(
|
|
276
|
+
AIPPanel(
|
|
277
|
+
f"[{ERROR_STYLE}]❌ Configuration incomplete[/]\n\n"
|
|
278
|
+
f"🔍 Current config:\n"
|
|
279
|
+
f" • API URL: {config.get('api_url', 'Not set')}\n"
|
|
280
|
+
f" • API Key: {'***' + config.get('api_key', '')[-4:] if config.get('api_key') else 'Not set'}\n\n"
|
|
281
|
+
f"💡 To fix this:\n"
|
|
282
|
+
f" • Run 'aip accounts add default' to set up credentials\n"
|
|
283
|
+
f" • Or run 'aip configure' for interactive setup\n"
|
|
284
|
+
f" • Or run 'aip accounts list' to see current accounts{no_accounts_hint}",
|
|
285
|
+
title="❌ Configuration Error",
|
|
286
|
+
border_style=ERROR,
|
|
287
|
+
),
|
|
288
|
+
)
|
|
289
|
+
console.print(f"\n[{SUCCESS_STYLE}]✅ AIP - Ready[/] (SDK v{sdk_version()}) - Configure to connect")
|
|
290
|
+
sys.exit(1)
|
|
260
291
|
|
|
261
292
|
|
|
262
293
|
def _resolve_status_console(ctx: Any) -> tuple[Console, bool]:
|
|
@@ -549,13 +580,39 @@ def update(check_only: bool, force: bool) -> None:
|
|
|
549
580
|
),
|
|
550
581
|
)
|
|
551
582
|
|
|
552
|
-
# Update using pip
|
|
583
|
+
# Update using pip or uv tool install
|
|
553
584
|
try:
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
585
|
+
is_uv = _is_uv_managed_environment()
|
|
586
|
+
if not is_uv and not _is_pip_available():
|
|
587
|
+
error_detail, troubleshooting = _build_missing_pip_guidance(
|
|
588
|
+
include_prerelease=False,
|
|
589
|
+
package_name="glaip-sdk",
|
|
590
|
+
force_reinstall=force,
|
|
591
|
+
)
|
|
592
|
+
console.print(
|
|
593
|
+
AIPPanel(
|
|
594
|
+
f"[{ERROR_STYLE}]❌ Update failed[/]\n\n🔍 Error: {error_detail}\n\n{troubleshooting}",
|
|
595
|
+
title=UPDATE_ERROR_TITLE,
|
|
596
|
+
border_style=ERROR,
|
|
597
|
+
padding=(0, 1),
|
|
598
|
+
),
|
|
599
|
+
)
|
|
600
|
+
sys.exit(1)
|
|
601
|
+
cmd = list(
|
|
602
|
+
_build_upgrade_command(
|
|
603
|
+
include_prerelease=False,
|
|
604
|
+
package_name="glaip-sdk",
|
|
605
|
+
is_uv=is_uv,
|
|
606
|
+
force_reinstall=force,
|
|
607
|
+
)
|
|
608
|
+
)
|
|
609
|
+
|
|
610
|
+
manual_cmd = _build_manual_upgrade_command(
|
|
611
|
+
include_prerelease=False,
|
|
612
|
+
package_name="glaip-sdk",
|
|
613
|
+
is_uv=is_uv,
|
|
614
|
+
force_reinstall=force,
|
|
615
|
+
)
|
|
559
616
|
subprocess.run(cmd, capture_output=True, text=True, check=True)
|
|
560
617
|
|
|
561
618
|
verify_hint = ""
|
|
@@ -582,16 +639,36 @@ def update(check_only: bool, force: bool) -> None:
|
|
|
582
639
|
)
|
|
583
640
|
console.print(f"📋 New version: {version_result.stdout.strip()}")
|
|
584
641
|
|
|
642
|
+
except FileNotFoundError:
|
|
643
|
+
troubleshooting = f"💡 Troubleshooting:\n • Try running: {manual_cmd}\n"
|
|
644
|
+
if is_uv:
|
|
645
|
+
troubleshooting += " • Ensure uv is installed: curl -LsSf https://astral.sh/uv/install.sh | sh"
|
|
646
|
+
error_detail = "uv executable not found in your PATH."
|
|
647
|
+
else:
|
|
648
|
+
troubleshooting += " • Ensure Python and pip are installed"
|
|
649
|
+
error_detail = "Python executable not found to run pip."
|
|
650
|
+
console.print(
|
|
651
|
+
AIPPanel(
|
|
652
|
+
f"[{ERROR_STYLE}]❌ Update failed[/]\n\n🔍 Error: {error_detail}\n\n{troubleshooting}",
|
|
653
|
+
title=UPDATE_ERROR_TITLE,
|
|
654
|
+
border_style=ERROR,
|
|
655
|
+
padding=(0, 1),
|
|
656
|
+
),
|
|
657
|
+
)
|
|
658
|
+
sys.exit(1)
|
|
585
659
|
except subprocess.CalledProcessError as e:
|
|
660
|
+
troubleshooting = (
|
|
661
|
+
f"💡 Troubleshooting:\n • Check your internet connection\n • Try running: {manual_cmd}\n"
|
|
662
|
+
)
|
|
663
|
+
if is_uv:
|
|
664
|
+
troubleshooting += " • Ensure uv is installed: curl -LsSf https://astral.sh/uv/install.sh | sh"
|
|
665
|
+
else:
|
|
666
|
+
troubleshooting += " • Check if you have write permissions"
|
|
667
|
+
|
|
586
668
|
console.print(
|
|
587
669
|
AIPPanel(
|
|
588
|
-
f"[{ERROR_STYLE}]❌ Update failed[/]\n\n"
|
|
589
|
-
|
|
590
|
-
"💡 Troubleshooting:\n"
|
|
591
|
-
" • Check your internet connection\n"
|
|
592
|
-
" • Try running: pip install --upgrade glaip-sdk\n"
|
|
593
|
-
" • Check if you have write permissions",
|
|
594
|
-
title="❌ Update Error",
|
|
670
|
+
f"[{ERROR_STYLE}]❌ Update failed[/]\n\n🔍 Error: {e.stderr}\n\n{troubleshooting}",
|
|
671
|
+
title=UPDATE_ERROR_TITLE,
|
|
595
672
|
border_style=ERROR,
|
|
596
673
|
padding=(0, 1),
|
|
597
674
|
),
|
glaip_sdk/cli/pager.py
CHANGED
|
@@ -46,11 +46,11 @@ def _get_console() -> Console:
|
|
|
46
46
|
"""
|
|
47
47
|
global console
|
|
48
48
|
try:
|
|
49
|
-
|
|
49
|
+
cli_output = importlib.import_module("glaip_sdk.cli.core.output")
|
|
50
50
|
except Exception: # pragma: no cover - fallback during import cycles
|
|
51
|
-
|
|
51
|
+
cli_output = None
|
|
52
52
|
|
|
53
|
-
current_console = getattr(
|
|
53
|
+
current_console = getattr(cli_output, "console", None) if cli_output else None
|
|
54
54
|
if current_console is not None and current_console is not console:
|
|
55
55
|
console = current_console
|
|
56
56
|
|
glaip_sdk/cli/resolution.py
CHANGED
|
@@ -13,7 +13,8 @@ from typing import Any
|
|
|
13
13
|
import click
|
|
14
14
|
|
|
15
15
|
from glaip_sdk.branding import ACCENT_STYLE
|
|
16
|
-
from glaip_sdk.cli.
|
|
16
|
+
from glaip_sdk.cli.core.output import resolve_resource
|
|
17
|
+
from glaip_sdk.cli.core.rendering import spinner_context
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
def resolve_resource_reference(
|
|
@@ -170,7 +170,9 @@ class AccountsController:
|
|
|
170
170
|
callbacks = AccountsTUICallbacks(switch_account=_switch_in_textual)
|
|
171
171
|
active = next((row["name"] for row in rows if row.get("active")), None)
|
|
172
172
|
try:
|
|
173
|
-
|
|
173
|
+
# Inject TUI context for theme support
|
|
174
|
+
tui_ctx = getattr(self.session, "tui_ctx", None)
|
|
175
|
+
run_accounts_textual(rows, active_account=active, env_lock=env_lock, callbacks=callbacks, ctx=tui_ctx)
|
|
174
176
|
except Exception as exc: # pragma: no cover - defensive around Textual failures
|
|
175
177
|
self.console.print(f"[{WARNING_STYLE}]Accounts browser exited unexpectedly: {exc}[/]")
|
|
176
178
|
|
|
@@ -17,7 +17,7 @@ from glaip_sdk.cli.commands.agents import run as agents_run_command
|
|
|
17
17
|
from glaip_sdk.cli.constants import DEFAULT_AGENT_INSTRUCTION_PREVIEW_LIMIT
|
|
18
18
|
from glaip_sdk.cli.hints import format_command_hint
|
|
19
19
|
from glaip_sdk.cli.slash.prompt import _HAS_PROMPT_TOOLKIT, FormattedText
|
|
20
|
-
from glaip_sdk.cli.
|
|
20
|
+
from glaip_sdk.cli.core.context import bind_slash_session_context
|
|
21
21
|
|
|
22
22
|
if TYPE_CHECKING: # pragma: no cover - type checking only
|
|
23
23
|
from glaip_sdk.cli.slash.session import SlashSession
|
|
@@ -30,7 +30,7 @@ from glaip_sdk.branding import (
|
|
|
30
30
|
)
|
|
31
31
|
from glaip_sdk.cli.constants import DEFAULT_REMOTE_RUNS_PAGE_LIMIT
|
|
32
32
|
from glaip_sdk.cli.slash.tui.remote_runs_app import RemoteRunsTUICallbacks, run_remote_runs_textual
|
|
33
|
-
from glaip_sdk.cli.
|
|
33
|
+
from glaip_sdk.cli.core.prompting import prompt_export_choice_questionary, questionary_safe_ask
|
|
34
34
|
from glaip_sdk.exceptions import (
|
|
35
35
|
AuthenticationError,
|
|
36
36
|
ForbiddenError,
|
|
@@ -294,12 +294,14 @@ class RemoteRunsController:
|
|
|
294
294
|
fetch_detail=fetch_detail,
|
|
295
295
|
export_run=export_run,
|
|
296
296
|
)
|
|
297
|
+
tui_ctx = getattr(self.session, "tui_ctx", None)
|
|
297
298
|
page, limit, cursor = run_remote_runs_textual(
|
|
298
299
|
runs_page,
|
|
299
300
|
state.get("cursor", 0),
|
|
300
301
|
callbacks,
|
|
301
302
|
agent_name=agent_name,
|
|
302
303
|
agent_id=agent_id,
|
|
304
|
+
ctx=tui_ctx,
|
|
303
305
|
)
|
|
304
306
|
state["page"] = page
|
|
305
307
|
state["limit"] = limit
|