glaip-sdk 0.6.15b2__py3-none-any.whl ā 0.6.15b3__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/__init__.py +27 -0
- glaip_sdk/agents/base.py +1196 -0
- glaip_sdk/cli/__init__.py +9 -0
- glaip_sdk/cli/account_store.py +540 -0
- glaip_sdk/cli/agent_config.py +78 -0
- glaip_sdk/cli/auth.py +699 -0
- glaip_sdk/cli/commands/__init__.py +5 -0
- glaip_sdk/cli/commands/accounts.py +746 -0
- glaip_sdk/cli/commands/agents.py +1509 -0
- glaip_sdk/cli/commands/common_config.py +104 -0
- glaip_sdk/cli/commands/configure.py +896 -0
- glaip_sdk/cli/commands/mcps.py +1356 -0
- glaip_sdk/cli/commands/models.py +69 -0
- glaip_sdk/cli/commands/tools.py +576 -0
- glaip_sdk/cli/commands/transcripts.py +755 -0
- glaip_sdk/cli/commands/update.py +61 -0
- glaip_sdk/cli/config.py +95 -0
- glaip_sdk/cli/constants.py +38 -0
- glaip_sdk/cli/context.py +150 -0
- glaip_sdk/cli/core/__init__.py +79 -0
- glaip_sdk/cli/core/context.py +124 -0
- glaip_sdk/cli/core/output.py +851 -0
- glaip_sdk/cli/core/prompting.py +649 -0
- glaip_sdk/cli/core/rendering.py +187 -0
- glaip_sdk/cli/display.py +355 -0
- glaip_sdk/cli/hints.py +57 -0
- glaip_sdk/cli/io.py +112 -0
- glaip_sdk/cli/main.py +615 -0
- glaip_sdk/cli/masking.py +136 -0
- glaip_sdk/cli/mcp_validators.py +287 -0
- glaip_sdk/cli/pager.py +266 -0
- glaip_sdk/cli/parsers/__init__.py +7 -0
- glaip_sdk/cli/parsers/json_input.py +177 -0
- glaip_sdk/cli/resolution.py +67 -0
- glaip_sdk/cli/rich_helpers.py +27 -0
- glaip_sdk/cli/slash/__init__.py +15 -0
- 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 +285 -0
- glaip_sdk/cli/slash/prompt.py +256 -0
- glaip_sdk/cli/slash/remote_runs_controller.py +566 -0
- glaip_sdk/cli/slash/session.py +1708 -0
- glaip_sdk/cli/slash/tui/__init__.py +9 -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 +31 -0
- glaip_sdk/cli/transcript/cache.py +536 -0
- glaip_sdk/cli/transcript/capture.py +329 -0
- glaip_sdk/cli/transcript/export.py +38 -0
- glaip_sdk/cli/transcript/history.py +815 -0
- glaip_sdk/cli/transcript/launcher.py +77 -0
- glaip_sdk/cli/transcript/viewer.py +374 -0
- glaip_sdk/cli/update_notifier.py +290 -0
- glaip_sdk/cli/utils.py +263 -0
- glaip_sdk/cli/validators.py +238 -0
- glaip_sdk/client/__init__.py +11 -0
- glaip_sdk/client/_agent_payloads.py +520 -0
- glaip_sdk/client/agent_runs.py +147 -0
- glaip_sdk/client/agents.py +1335 -0
- glaip_sdk/client/base.py +502 -0
- glaip_sdk/client/main.py +249 -0
- glaip_sdk/client/mcps.py +370 -0
- glaip_sdk/client/run_rendering.py +700 -0
- glaip_sdk/client/shared.py +21 -0
- glaip_sdk/client/tools.py +661 -0
- glaip_sdk/client/validators.py +198 -0
- glaip_sdk/config/constants.py +52 -0
- 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 +7 -0
- glaip_sdk/payload_schemas/agent.py +85 -0
- 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/runner/__init__.py +59 -0
- glaip_sdk/runner/base.py +84 -0
- glaip_sdk/runner/deps.py +112 -0
- glaip_sdk/runner/langgraph.py +782 -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 +86 -0
- glaip_sdk/utils/a2a/__init__.py +34 -0
- glaip_sdk/utils/a2a/event_processor.py +188 -0
- glaip_sdk/utils/agent_config.py +194 -0
- glaip_sdk/utils/bundler.py +267 -0
- glaip_sdk/utils/client.py +111 -0
- glaip_sdk/utils/client_utils.py +486 -0
- glaip_sdk/utils/datetime_helpers.py +58 -0
- glaip_sdk/utils/discovery.py +78 -0
- glaip_sdk/utils/display.py +135 -0
- glaip_sdk/utils/export.py +143 -0
- glaip_sdk/utils/general.py +61 -0
- glaip_sdk/utils/import_export.py +168 -0
- glaip_sdk/utils/import_resolver.py +492 -0
- glaip_sdk/utils/instructions.py +101 -0
- glaip_sdk/utils/rendering/__init__.py +115 -0
- glaip_sdk/utils/rendering/formatting.py +264 -0
- glaip_sdk/utils/rendering/layout/__init__.py +64 -0
- glaip_sdk/utils/rendering/layout/panels.py +156 -0
- glaip_sdk/utils/rendering/layout/progress.py +202 -0
- glaip_sdk/utils/rendering/layout/summary.py +74 -0
- glaip_sdk/utils/rendering/layout/transcript.py +606 -0
- glaip_sdk/utils/rendering/models.py +85 -0
- glaip_sdk/utils/rendering/renderer/__init__.py +55 -0
- glaip_sdk/utils/rendering/renderer/base.py +1024 -0
- glaip_sdk/utils/rendering/renderer/config.py +27 -0
- glaip_sdk/utils/rendering/renderer/console.py +55 -0
- glaip_sdk/utils/rendering/renderer/debug.py +178 -0
- glaip_sdk/utils/rendering/renderer/factory.py +138 -0
- glaip_sdk/utils/rendering/renderer/stream.py +202 -0
- 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 +182 -0
- 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 +100 -0
- glaip_sdk/utils/rendering/steps/__init__.py +34 -0
- glaip_sdk/utils/rendering/steps/event_processor.py +778 -0
- 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 +195 -0
- glaip_sdk/utils/run_renderer.py +41 -0
- glaip_sdk/utils/runtime_config.py +425 -0
- glaip_sdk/utils/serialization.py +424 -0
- glaip_sdk/utils/sync.py +142 -0
- glaip_sdk/utils/tool_detection.py +33 -0
- glaip_sdk/utils/validation.py +264 -0
- {glaip_sdk-0.6.15b2.dist-info ā glaip_sdk-0.6.15b3.dist-info}/METADATA +1 -1
- glaip_sdk-0.6.15b3.dist-info/RECORD +160 -0
- glaip_sdk-0.6.15b2.dist-info/RECORD +0 -12
- {glaip_sdk-0.6.15b2.dist-info ā glaip_sdk-0.6.15b3.dist-info}/WHEEL +0 -0
- {glaip_sdk-0.6.15b2.dist-info ā glaip_sdk-0.6.15b3.dist-info}/entry_points.txt +0 -0
- {glaip_sdk-0.6.15b2.dist-info ā glaip_sdk-0.6.15b3.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"""JSON input parser for CLI options.
|
|
2
|
+
|
|
3
|
+
Handles both inline JSON strings and @file references.
|
|
4
|
+
|
|
5
|
+
Authors:
|
|
6
|
+
Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
import os
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
import click
|
|
15
|
+
import yaml
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _looks_like_file_path(value: str) -> bool:
|
|
19
|
+
"""Check if string looks like a file reference.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
value: String to check for file-like patterns
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
True if the string appears to be a file path
|
|
26
|
+
"""
|
|
27
|
+
return (
|
|
28
|
+
value.lower().endswith((".json", ".yaml", ".yml"))
|
|
29
|
+
or "/" in value
|
|
30
|
+
or "\\" in value # Path separators
|
|
31
|
+
or value.startswith(("./", "../")) # Relative paths
|
|
32
|
+
or value.count(".") > 1 # Likely a filename with extension
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _format_file_error(prefix: str, file_path_str: str, resolved_path: Path, *, detail: str | None = None) -> str:
|
|
37
|
+
r"""Format a file-related error message with path context.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
prefix: Main error message
|
|
41
|
+
file_path_str: Original file path string provided by user
|
|
42
|
+
resolved_path: Resolved absolute path
|
|
43
|
+
detail: Optional additional detail to append
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
Formatted error message string with file path context
|
|
47
|
+
|
|
48
|
+
Examples:
|
|
49
|
+
>>> from pathlib import Path
|
|
50
|
+
>>> _format_file_error("File not found", "config.json", Path("/abs/config.json"))
|
|
51
|
+
'File not found: config.json\nResolved path: /abs/config.json'
|
|
52
|
+
"""
|
|
53
|
+
parts = [f"{prefix}: {file_path_str}", f"Resolved path: {resolved_path}"]
|
|
54
|
+
if detail:
|
|
55
|
+
parts.append(detail)
|
|
56
|
+
return "\n".join(parts)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _parse_json_from_file(file_path_str: str) -> Any:
|
|
60
|
+
"""Parse JSON or YAML from a file path.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
file_path_str: Path to the JSON or YAML file (without @ prefix).
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
Parsed dictionary from file.
|
|
67
|
+
|
|
68
|
+
Raises:
|
|
69
|
+
click.ClickException: If file not found, not readable, empty, or invalid format.
|
|
70
|
+
"""
|
|
71
|
+
# Resolve relative paths against CWD
|
|
72
|
+
file_path = Path(file_path_str)
|
|
73
|
+
if not file_path.is_absolute():
|
|
74
|
+
file_path = Path.cwd() / file_path
|
|
75
|
+
|
|
76
|
+
# Check if file exists and is a regular file
|
|
77
|
+
if not file_path.is_file():
|
|
78
|
+
raise click.ClickException(_format_file_error("File not found or not a file", file_path_str, file_path))
|
|
79
|
+
|
|
80
|
+
# Check if file is readable
|
|
81
|
+
if not os.access(file_path, os.R_OK):
|
|
82
|
+
raise click.ClickException(
|
|
83
|
+
_format_file_error("File not readable (permission denied)", file_path_str, file_path)
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
# Read file content
|
|
87
|
+
try:
|
|
88
|
+
content = file_path.read_text(encoding="utf-8")
|
|
89
|
+
except Exception as e:
|
|
90
|
+
raise click.ClickException(
|
|
91
|
+
_format_file_error("Error reading file", file_path_str, file_path, detail=f"Error: {e}")
|
|
92
|
+
) from e
|
|
93
|
+
|
|
94
|
+
# Check for empty content
|
|
95
|
+
if not content.strip():
|
|
96
|
+
raise click.ClickException(_format_file_error("File is empty", file_path_str, file_path))
|
|
97
|
+
|
|
98
|
+
# Determine file format and parse accordingly
|
|
99
|
+
file_ext = file_path.suffix.lower()
|
|
100
|
+
|
|
101
|
+
if file_ext in [".yaml", ".yml"]:
|
|
102
|
+
# Parse YAML from file content
|
|
103
|
+
try:
|
|
104
|
+
return yaml.safe_load(content)
|
|
105
|
+
except yaml.YAMLError as e:
|
|
106
|
+
raise click.ClickException(
|
|
107
|
+
_format_file_error(
|
|
108
|
+
"Invalid YAML in file",
|
|
109
|
+
file_path_str,
|
|
110
|
+
file_path,
|
|
111
|
+
detail=f"Error: {e}",
|
|
112
|
+
)
|
|
113
|
+
) from e
|
|
114
|
+
else:
|
|
115
|
+
# Default to JSON parsing
|
|
116
|
+
try:
|
|
117
|
+
return json.loads(content)
|
|
118
|
+
except json.JSONDecodeError as e:
|
|
119
|
+
raise click.ClickException(
|
|
120
|
+
_format_file_error(
|
|
121
|
+
"Invalid JSON in file",
|
|
122
|
+
file_path_str,
|
|
123
|
+
file_path,
|
|
124
|
+
detail=f"Error: {e.msg} at line {e.lineno}, column {e.colno}",
|
|
125
|
+
)
|
|
126
|
+
) from e
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def parse_json_input(value: str | None) -> Any:
|
|
130
|
+
"""Parse JSON input from inline string or file reference.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
value: JSON string or @file reference. If None, returns None.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
Parsed JSON value (dict, list, str, int, float, bool, None) or None if value is None.
|
|
137
|
+
|
|
138
|
+
Raises:
|
|
139
|
+
click.ClickException: If file not found, not readable, empty, or invalid JSON.
|
|
140
|
+
|
|
141
|
+
Examples:
|
|
142
|
+
>>> parse_json_input('{"key": "value"}')
|
|
143
|
+
{'key': 'value'}
|
|
144
|
+
|
|
145
|
+
>>> parse_json_input('@/path/to/config.json')
|
|
146
|
+
# Returns content of config.json parsed as JSON
|
|
147
|
+
|
|
148
|
+
>>> parse_json_input('/path/to/config.json')
|
|
149
|
+
# Fallback: treats as file path if JSON parsing fails
|
|
150
|
+
|
|
151
|
+
>>> parse_json_input(None)
|
|
152
|
+
None
|
|
153
|
+
"""
|
|
154
|
+
if value is None:
|
|
155
|
+
return None
|
|
156
|
+
|
|
157
|
+
# Check if value is a file reference (strip whitespace first)
|
|
158
|
+
trimmed = value.strip()
|
|
159
|
+
if trimmed.startswith("@"):
|
|
160
|
+
return _parse_json_from_file(trimmed[1:])
|
|
161
|
+
|
|
162
|
+
# Parse inline JSON
|
|
163
|
+
try:
|
|
164
|
+
return json.loads(value)
|
|
165
|
+
except json.JSONDecodeError as e:
|
|
166
|
+
# Check if the value looks like a file path and provide helpful hint
|
|
167
|
+
if _looks_like_file_path(trimmed):
|
|
168
|
+
raise click.ClickException(
|
|
169
|
+
f"Invalid JSON in inline value\n"
|
|
170
|
+
f"Error: {e.msg} at line {e.lineno}, column {e.colno}\n"
|
|
171
|
+
f"\nš” Did you mean to load this from a file? "
|
|
172
|
+
f"File-based config values should start with @ (e.g., @{trimmed})"
|
|
173
|
+
) from e
|
|
174
|
+
|
|
175
|
+
raise click.ClickException(
|
|
176
|
+
f"Invalid JSON in inline value\nError: {e.msg} at line {e.lineno}, column {e.colno}"
|
|
177
|
+
) from e
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""CLI resource resolution utilities for handling ID/name references.
|
|
2
|
+
|
|
3
|
+
This module provides CLI-specific resource resolution functionality,
|
|
4
|
+
including interactive pickers and ambiguity handling.
|
|
5
|
+
|
|
6
|
+
Authors:
|
|
7
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from collections.abc import Callable
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
import click
|
|
14
|
+
|
|
15
|
+
from glaip_sdk.branding import ACCENT_STYLE
|
|
16
|
+
from glaip_sdk.cli.utils import resolve_resource, spinner_context
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def resolve_resource_reference(
|
|
20
|
+
ctx: Any,
|
|
21
|
+
_client: Any,
|
|
22
|
+
reference: str,
|
|
23
|
+
resource_type: str,
|
|
24
|
+
get_by_id_func: Callable,
|
|
25
|
+
find_by_name_func: Callable,
|
|
26
|
+
label: str,
|
|
27
|
+
select: int | None = None,
|
|
28
|
+
interface_preference: str | None = None,
|
|
29
|
+
spinner_message: str | None = None,
|
|
30
|
+
) -> Any | None:
|
|
31
|
+
"""Resolve resource reference (ID or name) with ambiguity handling.
|
|
32
|
+
|
|
33
|
+
This is a common pattern used across all resource types.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
ctx: Click context for CLI operations.
|
|
37
|
+
_client: API client instance for backend operations.
|
|
38
|
+
reference: Resource ID or name to resolve.
|
|
39
|
+
resource_type: Type of resource being resolved.
|
|
40
|
+
get_by_id_func: Function to get resource by ID.
|
|
41
|
+
find_by_name_func: Function to find resources by name.
|
|
42
|
+
label: Label for error messages and user feedback.
|
|
43
|
+
select: Selection index for ambiguous matches in non-interactive mode.
|
|
44
|
+
interface_preference: Interface preference for user interaction ("fuzzy" or "questionary").
|
|
45
|
+
spinner_message: Custom message to show during resolution process.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
Resolved resource object or None if not found.
|
|
49
|
+
|
|
50
|
+
Raises:
|
|
51
|
+
click.ClickException: If resolution fails.
|
|
52
|
+
"""
|
|
53
|
+
try:
|
|
54
|
+
message = spinner_message if spinner_message is not None else f"[bold blue]Fetching {label}ā¦[/bold blue]"
|
|
55
|
+
with spinner_context(ctx, message, spinner_style=ACCENT_STYLE) as status_indicator:
|
|
56
|
+
return resolve_resource(
|
|
57
|
+
ctx,
|
|
58
|
+
reference,
|
|
59
|
+
get_by_id=get_by_id_func,
|
|
60
|
+
find_by_name=find_by_name_func,
|
|
61
|
+
label=label,
|
|
62
|
+
select=select,
|
|
63
|
+
interface_preference=interface_preference,
|
|
64
|
+
status_indicator=status_indicator,
|
|
65
|
+
)
|
|
66
|
+
except Exception as e:
|
|
67
|
+
raise click.ClickException(f"Failed to resolve {resource_type.lower()}: {e}") from e
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Shared helpers for creating and printing Rich markup content.
|
|
2
|
+
|
|
3
|
+
Authors:
|
|
4
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from rich.console import Console
|
|
12
|
+
from rich.markup import MarkupError
|
|
13
|
+
from rich.text import Text
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def markup_text(message: str, **kwargs: Any) -> Text:
|
|
17
|
+
"""Create a Rich Text instance from markup with graceful fallback."""
|
|
18
|
+
try:
|
|
19
|
+
return Text.from_markup(message, **kwargs)
|
|
20
|
+
except MarkupError:
|
|
21
|
+
return Text(message, **kwargs)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def print_markup(message: str, *, console: Console | None = None, **kwargs: Any) -> None:
|
|
25
|
+
"""Print markup-aware text to the provided console (default: new Console)."""
|
|
26
|
+
target_console = console or Console()
|
|
27
|
+
target_console.print(markup_text(message, **kwargs))
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Slash command palette entrypoints.
|
|
2
|
+
|
|
3
|
+
Authors:
|
|
4
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from glaip_sdk.cli.commands.agents import get as agents_get_command
|
|
8
|
+
from glaip_sdk.cli.commands.agents import run as agents_run_command
|
|
9
|
+
from glaip_sdk.cli.slash.session import SlashSession
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"SlashSession",
|
|
13
|
+
"agents_get_command",
|
|
14
|
+
"agents_run_command",
|
|
15
|
+
]
|