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.
Files changed (154) hide show
  1. glaip_sdk/agents/__init__.py +27 -0
  2. glaip_sdk/agents/base.py +1196 -0
  3. glaip_sdk/cli/__init__.py +9 -0
  4. glaip_sdk/cli/account_store.py +540 -0
  5. glaip_sdk/cli/agent_config.py +78 -0
  6. glaip_sdk/cli/auth.py +699 -0
  7. glaip_sdk/cli/commands/__init__.py +5 -0
  8. glaip_sdk/cli/commands/accounts.py +746 -0
  9. glaip_sdk/cli/commands/agents.py +1509 -0
  10. glaip_sdk/cli/commands/common_config.py +104 -0
  11. glaip_sdk/cli/commands/configure.py +896 -0
  12. glaip_sdk/cli/commands/mcps.py +1356 -0
  13. glaip_sdk/cli/commands/models.py +69 -0
  14. glaip_sdk/cli/commands/tools.py +576 -0
  15. glaip_sdk/cli/commands/transcripts.py +755 -0
  16. glaip_sdk/cli/commands/update.py +61 -0
  17. glaip_sdk/cli/config.py +95 -0
  18. glaip_sdk/cli/constants.py +38 -0
  19. glaip_sdk/cli/context.py +150 -0
  20. glaip_sdk/cli/core/__init__.py +79 -0
  21. glaip_sdk/cli/core/context.py +124 -0
  22. glaip_sdk/cli/core/output.py +851 -0
  23. glaip_sdk/cli/core/prompting.py +649 -0
  24. glaip_sdk/cli/core/rendering.py +187 -0
  25. glaip_sdk/cli/display.py +355 -0
  26. glaip_sdk/cli/hints.py +57 -0
  27. glaip_sdk/cli/io.py +112 -0
  28. glaip_sdk/cli/main.py +615 -0
  29. glaip_sdk/cli/masking.py +136 -0
  30. glaip_sdk/cli/mcp_validators.py +287 -0
  31. glaip_sdk/cli/pager.py +266 -0
  32. glaip_sdk/cli/parsers/__init__.py +7 -0
  33. glaip_sdk/cli/parsers/json_input.py +177 -0
  34. glaip_sdk/cli/resolution.py +67 -0
  35. glaip_sdk/cli/rich_helpers.py +27 -0
  36. glaip_sdk/cli/slash/__init__.py +15 -0
  37. glaip_sdk/cli/slash/accounts_controller.py +578 -0
  38. glaip_sdk/cli/slash/accounts_shared.py +75 -0
  39. glaip_sdk/cli/slash/agent_session.py +285 -0
  40. glaip_sdk/cli/slash/prompt.py +256 -0
  41. glaip_sdk/cli/slash/remote_runs_controller.py +566 -0
  42. glaip_sdk/cli/slash/session.py +1708 -0
  43. glaip_sdk/cli/slash/tui/__init__.py +9 -0
  44. glaip_sdk/cli/slash/tui/accounts_app.py +876 -0
  45. glaip_sdk/cli/slash/tui/background_tasks.py +72 -0
  46. glaip_sdk/cli/slash/tui/loading.py +58 -0
  47. glaip_sdk/cli/slash/tui/remote_runs_app.py +628 -0
  48. glaip_sdk/cli/transcript/__init__.py +31 -0
  49. glaip_sdk/cli/transcript/cache.py +536 -0
  50. glaip_sdk/cli/transcript/capture.py +329 -0
  51. glaip_sdk/cli/transcript/export.py +38 -0
  52. glaip_sdk/cli/transcript/history.py +815 -0
  53. glaip_sdk/cli/transcript/launcher.py +77 -0
  54. glaip_sdk/cli/transcript/viewer.py +374 -0
  55. glaip_sdk/cli/update_notifier.py +290 -0
  56. glaip_sdk/cli/utils.py +263 -0
  57. glaip_sdk/cli/validators.py +238 -0
  58. glaip_sdk/client/__init__.py +11 -0
  59. glaip_sdk/client/_agent_payloads.py +520 -0
  60. glaip_sdk/client/agent_runs.py +147 -0
  61. glaip_sdk/client/agents.py +1335 -0
  62. glaip_sdk/client/base.py +502 -0
  63. glaip_sdk/client/main.py +249 -0
  64. glaip_sdk/client/mcps.py +370 -0
  65. glaip_sdk/client/run_rendering.py +700 -0
  66. glaip_sdk/client/shared.py +21 -0
  67. glaip_sdk/client/tools.py +661 -0
  68. glaip_sdk/client/validators.py +198 -0
  69. glaip_sdk/config/constants.py +52 -0
  70. glaip_sdk/mcps/__init__.py +21 -0
  71. glaip_sdk/mcps/base.py +345 -0
  72. glaip_sdk/models/__init__.py +90 -0
  73. glaip_sdk/models/agent.py +47 -0
  74. glaip_sdk/models/agent_runs.py +116 -0
  75. glaip_sdk/models/common.py +42 -0
  76. glaip_sdk/models/mcp.py +33 -0
  77. glaip_sdk/models/tool.py +33 -0
  78. glaip_sdk/payload_schemas/__init__.py +7 -0
  79. glaip_sdk/payload_schemas/agent.py +85 -0
  80. glaip_sdk/registry/__init__.py +55 -0
  81. glaip_sdk/registry/agent.py +164 -0
  82. glaip_sdk/registry/base.py +139 -0
  83. glaip_sdk/registry/mcp.py +253 -0
  84. glaip_sdk/registry/tool.py +232 -0
  85. glaip_sdk/runner/__init__.py +59 -0
  86. glaip_sdk/runner/base.py +84 -0
  87. glaip_sdk/runner/deps.py +112 -0
  88. glaip_sdk/runner/langgraph.py +782 -0
  89. glaip_sdk/runner/mcp_adapter/__init__.py +13 -0
  90. glaip_sdk/runner/mcp_adapter/base_mcp_adapter.py +43 -0
  91. glaip_sdk/runner/mcp_adapter/langchain_mcp_adapter.py +257 -0
  92. glaip_sdk/runner/mcp_adapter/mcp_config_builder.py +95 -0
  93. glaip_sdk/runner/tool_adapter/__init__.py +18 -0
  94. glaip_sdk/runner/tool_adapter/base_tool_adapter.py +44 -0
  95. glaip_sdk/runner/tool_adapter/langchain_tool_adapter.py +219 -0
  96. glaip_sdk/tools/__init__.py +22 -0
  97. glaip_sdk/tools/base.py +435 -0
  98. glaip_sdk/utils/__init__.py +86 -0
  99. glaip_sdk/utils/a2a/__init__.py +34 -0
  100. glaip_sdk/utils/a2a/event_processor.py +188 -0
  101. glaip_sdk/utils/agent_config.py +194 -0
  102. glaip_sdk/utils/bundler.py +267 -0
  103. glaip_sdk/utils/client.py +111 -0
  104. glaip_sdk/utils/client_utils.py +486 -0
  105. glaip_sdk/utils/datetime_helpers.py +58 -0
  106. glaip_sdk/utils/discovery.py +78 -0
  107. glaip_sdk/utils/display.py +135 -0
  108. glaip_sdk/utils/export.py +143 -0
  109. glaip_sdk/utils/general.py +61 -0
  110. glaip_sdk/utils/import_export.py +168 -0
  111. glaip_sdk/utils/import_resolver.py +492 -0
  112. glaip_sdk/utils/instructions.py +101 -0
  113. glaip_sdk/utils/rendering/__init__.py +115 -0
  114. glaip_sdk/utils/rendering/formatting.py +264 -0
  115. glaip_sdk/utils/rendering/layout/__init__.py +64 -0
  116. glaip_sdk/utils/rendering/layout/panels.py +156 -0
  117. glaip_sdk/utils/rendering/layout/progress.py +202 -0
  118. glaip_sdk/utils/rendering/layout/summary.py +74 -0
  119. glaip_sdk/utils/rendering/layout/transcript.py +606 -0
  120. glaip_sdk/utils/rendering/models.py +85 -0
  121. glaip_sdk/utils/rendering/renderer/__init__.py +55 -0
  122. glaip_sdk/utils/rendering/renderer/base.py +1024 -0
  123. glaip_sdk/utils/rendering/renderer/config.py +27 -0
  124. glaip_sdk/utils/rendering/renderer/console.py +55 -0
  125. glaip_sdk/utils/rendering/renderer/debug.py +178 -0
  126. glaip_sdk/utils/rendering/renderer/factory.py +138 -0
  127. glaip_sdk/utils/rendering/renderer/stream.py +202 -0
  128. glaip_sdk/utils/rendering/renderer/summary_window.py +79 -0
  129. glaip_sdk/utils/rendering/renderer/thinking.py +273 -0
  130. glaip_sdk/utils/rendering/renderer/toggle.py +182 -0
  131. glaip_sdk/utils/rendering/renderer/tool_panels.py +442 -0
  132. glaip_sdk/utils/rendering/renderer/transcript_mode.py +162 -0
  133. glaip_sdk/utils/rendering/state.py +204 -0
  134. glaip_sdk/utils/rendering/step_tree_state.py +100 -0
  135. glaip_sdk/utils/rendering/steps/__init__.py +34 -0
  136. glaip_sdk/utils/rendering/steps/event_processor.py +778 -0
  137. glaip_sdk/utils/rendering/steps/format.py +176 -0
  138. glaip_sdk/utils/rendering/steps/manager.py +387 -0
  139. glaip_sdk/utils/rendering/timing.py +36 -0
  140. glaip_sdk/utils/rendering/viewer/__init__.py +21 -0
  141. glaip_sdk/utils/rendering/viewer/presenter.py +184 -0
  142. glaip_sdk/utils/resource_refs.py +195 -0
  143. glaip_sdk/utils/run_renderer.py +41 -0
  144. glaip_sdk/utils/runtime_config.py +425 -0
  145. glaip_sdk/utils/serialization.py +424 -0
  146. glaip_sdk/utils/sync.py +142 -0
  147. glaip_sdk/utils/tool_detection.py +33 -0
  148. glaip_sdk/utils/validation.py +264 -0
  149. {glaip_sdk-0.6.15b2.dist-info → glaip_sdk-0.6.15b3.dist-info}/METADATA +1 -1
  150. glaip_sdk-0.6.15b3.dist-info/RECORD +160 -0
  151. glaip_sdk-0.6.15b2.dist-info/RECORD +0 -12
  152. {glaip_sdk-0.6.15b2.dist-info → glaip_sdk-0.6.15b3.dist-info}/WHEEL +0 -0
  153. {glaip_sdk-0.6.15b2.dist-info → glaip_sdk-0.6.15b3.dist-info}/entry_points.txt +0 -0
  154. {glaip_sdk-0.6.15b2.dist-info → glaip_sdk-0.6.15b3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,184 @@
1
+ """Shared presenter utilities for CLI/offline transcript viewing.
2
+
3
+ Authors:
4
+ Raymond Christopher (raymond.christopher@gdplabs.id)
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from dataclasses import dataclass
10
+ from typing import Any
11
+
12
+ from rich.console import Console
13
+
14
+ from glaip_sdk.utils.rendering.layout.transcript import (
15
+ DEFAULT_TRANSCRIPT_THEME,
16
+ TranscriptGlyphs,
17
+ TranscriptSnapshot,
18
+ build_transcript_snapshot,
19
+ build_transcript_view,
20
+ )
21
+ from glaip_sdk.utils.rendering.renderer.debug import render_debug_event_stream
22
+ from glaip_sdk.utils.rendering.state import RendererState, coerce_received_at
23
+ from glaip_sdk.utils.rendering.steps import StepManager
24
+
25
+
26
+ @dataclass(slots=True)
27
+ class ViewerContext:
28
+ """Runtime context passed to transcript presenters."""
29
+
30
+ manifest_entry: dict[str, Any]
31
+ events: list[dict[str, Any]]
32
+ default_output: str
33
+ final_output: str
34
+ stream_started_at: float | None
35
+ meta: dict[str, Any]
36
+
37
+
38
+ def render_post_run_view(
39
+ console: Console,
40
+ ctx: ViewerContext,
41
+ *,
42
+ glyphs: TranscriptGlyphs | None = None,
43
+ theme: str = DEFAULT_TRANSCRIPT_THEME,
44
+ ) -> TranscriptSnapshot:
45
+ """Render the default summary view and return the snapshot used."""
46
+ snapshot, _state = prepare_viewer_snapshot(
47
+ ctx,
48
+ glyphs=glyphs,
49
+ theme=theme,
50
+ )
51
+ render_transcript_view(console, snapshot, theme=theme)
52
+ return snapshot
53
+
54
+
55
+ def render_transcript_view(
56
+ console: Console,
57
+ snapshot: TranscriptSnapshot,
58
+ *,
59
+ theme: str = DEFAULT_TRANSCRIPT_THEME,
60
+ ) -> None:
61
+ """Render the transcript summary using a prepared snapshot."""
62
+ header, body = build_transcript_view(snapshot, theme=theme)
63
+ _print_renderables(console, header + body)
64
+
65
+
66
+ def render_transcript_events(console: Console, events: list[dict[str, Any]]) -> None:
67
+ """Pretty-print transcript events using shared debug presenter."""
68
+ if not events:
69
+ console.print("[dim]No SSE events were captured for this run.[/dim]")
70
+ console.print()
71
+ return
72
+
73
+ console.print("[bold]Transcript Events[/bold]")
74
+ console.print("[dim]────────────────────────────────────────────────────────[/dim]")
75
+
76
+ render_debug_event_stream(
77
+ events,
78
+ console,
79
+ resolve_timestamp=lambda event: coerce_received_at(event.get("received_at")),
80
+ )
81
+ console.print()
82
+
83
+
84
+ def prepare_viewer_snapshot(
85
+ ctx: ViewerContext,
86
+ *,
87
+ glyphs: TranscriptGlyphs | None,
88
+ theme: str,
89
+ ) -> tuple[TranscriptSnapshot, RendererState]:
90
+ """Build a transcript snapshot plus renderer state for reusable viewing."""
91
+ state = _build_renderer_state(ctx)
92
+ manager = _build_steps_from_events(ctx.events)
93
+ query = _extract_query_from_manifest(ctx)
94
+ merged_meta = _merge_meta(ctx)
95
+ snapshot = build_transcript_snapshot(
96
+ state,
97
+ manager,
98
+ glyphs=glyphs,
99
+ query_text=query,
100
+ meta=merged_meta,
101
+ theme=theme,
102
+ )
103
+ return snapshot, state
104
+
105
+
106
+ def _build_renderer_state(ctx: ViewerContext) -> RendererState:
107
+ state = RendererState()
108
+ state.meta = dict(ctx.meta or {})
109
+
110
+ final_text = (ctx.final_output or "").strip()
111
+ default_text = (ctx.default_output or "").strip()
112
+ if final_text:
113
+ state.final_text = final_text
114
+ elif default_text:
115
+ state.final_text = default_text
116
+ state.buffer.append(default_text)
117
+
118
+ duration = _extract_final_duration(ctx.events)
119
+ if duration:
120
+ state.final_duration_text = duration # pragma: no cover - exercised indirectly via end-to-end tests
121
+ state.events = list(ctx.events or [])
122
+ return state
123
+
124
+
125
+ def _build_steps_from_events(events: list[dict[str, Any]]) -> StepManager:
126
+ manager = StepManager()
127
+ for event in events or []:
128
+ payload = _coerce_step_event(event)
129
+ if not payload:
130
+ continue
131
+ try:
132
+ manager.apply_event(payload)
133
+ except ValueError:
134
+ continue
135
+ return manager
136
+
137
+
138
+ def _coerce_step_event(event: dict[str, Any]) -> dict[str, Any] | None:
139
+ metadata = event.get("metadata")
140
+ if not isinstance(metadata, dict):
141
+ return None
142
+ if not isinstance(metadata.get("step_id"), str):
143
+ return None
144
+ return {
145
+ "metadata": metadata,
146
+ "status": event.get("status"),
147
+ "task_state": event.get("task_state"),
148
+ "content": event.get("content"),
149
+ "task_id": event.get("task_id"),
150
+ "context_id": event.get("context_id"),
151
+ }
152
+
153
+
154
+ def _extract_final_duration(events: list[dict[str, Any]]) -> str | None:
155
+ for event in events or []:
156
+ metadata = event.get("metadata") or {}
157
+ if metadata.get("kind") != "final_response":
158
+ continue
159
+ time_value = metadata.get("time")
160
+ if isinstance(time_value, (int, float)):
161
+ return f"{float(time_value):.2f}s"
162
+ return None
163
+
164
+
165
+ def _extract_query_from_manifest(ctx: ViewerContext) -> str | None:
166
+ query = ctx.manifest_entry.get("input_message") or ctx.meta.get("input_message") or ctx.meta.get("query")
167
+ if isinstance(query, str) and query.strip():
168
+ return query.strip()
169
+ return None
170
+
171
+
172
+ def _merge_meta(ctx: ViewerContext) -> dict[str, Any]:
173
+ merged = dict(ctx.meta or {})
174
+ manifest = ctx.manifest_entry or {}
175
+ for key in ("agent_name", "agent_id", "model", "run_id", "input_message"):
176
+ if key in manifest and manifest[key] and key not in merged:
177
+ merged[key] = manifest[key]
178
+ return merged
179
+
180
+
181
+ def _print_renderables(console: Console, renderables: list[Any]) -> None:
182
+ for renderable in renderables:
183
+ console.print(renderable)
184
+ console.print()
@@ -0,0 +1,195 @@
1
+ """Resource reference utilities for ID/name extraction and UUID detection.
2
+
3
+ This module provides normalized helpers for working with resource references
4
+ across the SDK, consolidating logic that was previously duplicated between
5
+ CLI and SDK layers.
6
+
7
+ Authors:
8
+ Raymond Christopher (raymond.christopher@gdplabs.id)
9
+ """
10
+
11
+ import re
12
+ from typing import Any
13
+ from uuid import UUID
14
+
15
+
16
+ def is_uuid(value: str) -> bool:
17
+ """Check if a string is a valid UUID.
18
+
19
+ Args:
20
+ value: String to check
21
+
22
+ Returns:
23
+ True if value is a valid UUID, False otherwise
24
+ """
25
+ try:
26
+ UUID(value)
27
+ return True
28
+ except (ValueError, TypeError):
29
+ return False
30
+
31
+
32
+ def _extract_id_from_item(item: Any, *, skip_missing: bool = False) -> str | None:
33
+ """Extract ID from a single item.
34
+
35
+ Args:
36
+ item: Item that may be a string, object with .id, or dict with "id" key.
37
+ skip_missing: If True, return None for items without IDs. If False, convert to string.
38
+
39
+ Returns:
40
+ Extracted ID as string, or None if skip_missing=True and no ID found.
41
+ """
42
+ if isinstance(item, str):
43
+ return item
44
+ if hasattr(item, "id"):
45
+ return str(item.id)
46
+ if isinstance(item, dict) and "id" in item:
47
+ return str(item["id"])
48
+ if skip_missing:
49
+ return None
50
+ # Fallback: convert to string
51
+ return str(item)
52
+
53
+
54
+ def extract_ids(items: list[str | Any] | None) -> list[str]:
55
+ """Extract IDs from a list of objects or strings.
56
+
57
+ This function unifies the behavior between CLI and SDK layers, always
58
+ returning a list (empty list for None/empty input) rather than None.
59
+
60
+ Args:
61
+ items: List of items that may be strings, objects with .id, or other types
62
+
63
+ Returns:
64
+ List of extracted IDs (empty list if items is None/empty)
65
+
66
+ Examples:
67
+ extract_ids([{"id": "123"}, "456"]) -> ["123", "456"]
68
+ extract_ids(None) -> []
69
+ extract_ids([]) -> []
70
+ """
71
+ if not items:
72
+ return []
73
+
74
+ # Extract IDs from all items, converting non-ID items to strings
75
+ extracted_ids = [_extract_id_from_item(item, skip_missing=False) for item in items]
76
+ return [id_val for id_val in extracted_ids if id_val is not None]
77
+
78
+
79
+ def extract_names(items: list[str | Any] | None) -> list[str]:
80
+ """Extract names from a list of objects or strings.
81
+
82
+ Args:
83
+ items: List of items that may be strings, objects with .name, or other types
84
+
85
+ Returns:
86
+ List of extracted names (empty list if items is None/empty)
87
+
88
+ Examples:
89
+ extract_names([{"name": "tool1"}, "tool2"]) -> ["tool1", "tool2"]
90
+ extract_names(None) -> []
91
+ """
92
+ if not items:
93
+ return []
94
+
95
+ names = []
96
+ for item in items:
97
+ if isinstance(item, str):
98
+ names.append(item)
99
+ elif hasattr(item, "name"):
100
+ names.append(str(item.name))
101
+ elif isinstance(item, dict) and "name" in item:
102
+ names.append(str(item["name"]))
103
+ else:
104
+ # Fallback: convert to string
105
+ names.append(str(item))
106
+
107
+ return names
108
+
109
+
110
+ def find_by_name(items: list[Any], name: str, case_sensitive: bool = False) -> list[Any]:
111
+ """Filter items by name with optional case sensitivity.
112
+
113
+ This is a common pattern used across different clients for client-side
114
+ filtering when the backend doesn't support name query parameters.
115
+
116
+ Args:
117
+ items: List of items to filter
118
+ name: Name to search for
119
+ case_sensitive: Whether the search should be case sensitive
120
+
121
+ Returns:
122
+ Filtered list of items matching the name
123
+ """
124
+ if not name:
125
+ return items
126
+
127
+ if case_sensitive:
128
+ return [item for item in items if name in item.name]
129
+ else:
130
+ return [item for item in items if name.lower() in item.name.lower()]
131
+
132
+
133
+ def sanitize_name(name: str) -> str:
134
+ """Sanitize a name for resource creation.
135
+
136
+ Args:
137
+ name: Raw name input
138
+
139
+ Returns:
140
+ Sanitized name suitable for resource creation
141
+ """
142
+ # Remove special characters and normalize
143
+ sanitized = re.sub(r"[^a-zA-Z0-9\-_]", "-", name.strip())
144
+ sanitized = re.sub(r"-+", "-", sanitized) # Collapse multiple dashes
145
+ return sanitized.lower().strip("-")
146
+
147
+
148
+ def validate_name_format(name: str, resource_type: str = "resource") -> str:
149
+ """Validate resource name format and return cleaned version.
150
+
151
+ Args:
152
+ name: Name to validate
153
+ resource_type: Type of resource (for error messages)
154
+
155
+ Returns:
156
+ Cleaned name
157
+
158
+ Raises:
159
+ ValueError: If name format is invalid
160
+ """
161
+ # Map resource types to proper display names
162
+ type_display = {"agent": "Agent", "tool": "Tool", "mcp": "MCP"}
163
+ display_type = type_display.get(resource_type.lower(), resource_type.title())
164
+
165
+ if not name or not name.strip():
166
+ raise ValueError(f"{display_type} name cannot be empty")
167
+
168
+ cleaned_name = name.strip()
169
+
170
+ if len(cleaned_name) < 1:
171
+ raise ValueError(f"{display_type} name cannot be empty")
172
+
173
+ if len(cleaned_name) > 100:
174
+ raise ValueError(f"{display_type} name cannot be longer than 100 characters")
175
+
176
+ # Check for valid characters (alphanumeric, hyphens, underscores)
177
+ if not re.match(r"^[a-zA-Z0-9_-]+$", cleaned_name):
178
+ raise ValueError(f"{display_type} name can only contain letters, numbers, hyphens, and underscores")
179
+
180
+ return cleaned_name
181
+
182
+
183
+ def validate_name_uniqueness(name: str, existing_names: list[str], resource_type: str = "resource") -> None:
184
+ """Validate that a resource name is unique.
185
+
186
+ Args:
187
+ name: Name to validate
188
+ existing_names: List of existing names to check against
189
+ resource_type: Type of resource (for error messages)
190
+
191
+ Raises:
192
+ ValueError: If name is not unique
193
+ """
194
+ if name.lower() in [existing.lower() for existing in existing_names]:
195
+ raise ValueError(f"A {resource_type.lower()} named '{name}' already exists. Please choose a unique name.")
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env python3
2
+ """Modern run renderer for agent execution with clean streaming output.
3
+
4
+ This module provides a modern CLI experience similar to Claude Code and Gemini CLI,
5
+ with compact headers, streaming markdown, collapsible tool steps, and clean output.
6
+
7
+ This is a compatibility shim that re-exports components from the new modular renderer package.
8
+
9
+ Authors:
10
+ Raymond Christopher (raymond.christopher@gdplabs.id)
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ # Configure logger
16
+ import logging
17
+
18
+ from glaip_sdk.utils.rendering.models import RunStats
19
+
20
+ # Re-export main components from the new modular renderer package
21
+ from glaip_sdk.utils.rendering.renderer.base import RichStreamRenderer
22
+ from glaip_sdk.utils.rendering.renderer.config import RendererConfig
23
+ from glaip_sdk.utils.rendering.renderer.console import CapturingConsole
24
+
25
+ # Legacy imports for backward compatibility
26
+ from glaip_sdk.utils.rendering.renderer.debug import render_debug_event
27
+ from glaip_sdk.utils.rendering.steps import StepManager
28
+
29
+ logger = logging.getLogger("glaip_sdk.run_renderer")
30
+
31
+
32
+ # The full implementation has been moved to glaip_sdk.utils.rendering.renderer.base
33
+ # This file now serves as a compatibility shim for existing imports.
34
+ __all__ = [
35
+ "CapturingConsole",
36
+ "RendererConfig",
37
+ "RichStreamRenderer",
38
+ "RunStats",
39
+ "StepManager",
40
+ "render_debug_event",
41
+ ]