glaip-sdk 0.6.12__py3-none-any.whl → 0.6.14__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 +42 -5
- {glaip_sdk-0.6.12.dist-info → glaip_sdk-0.6.14.dist-info}/METADATA +31 -37
- glaip_sdk-0.6.14.dist-info/RECORD +12 -0
- {glaip_sdk-0.6.12.dist-info → glaip_sdk-0.6.14.dist-info}/WHEEL +2 -1
- glaip_sdk-0.6.14.dist-info/entry_points.txt +2 -0
- glaip_sdk-0.6.14.dist-info/top_level.txt +1 -0
- glaip_sdk/agents/__init__.py +0 -27
- glaip_sdk/agents/base.py +0 -1191
- glaip_sdk/cli/__init__.py +0 -9
- glaip_sdk/cli/account_store.py +0 -540
- glaip_sdk/cli/agent_config.py +0 -78
- glaip_sdk/cli/auth.py +0 -699
- glaip_sdk/cli/commands/__init__.py +0 -5
- glaip_sdk/cli/commands/accounts.py +0 -746
- glaip_sdk/cli/commands/agents.py +0 -1509
- glaip_sdk/cli/commands/common_config.py +0 -101
- glaip_sdk/cli/commands/configure.py +0 -896
- glaip_sdk/cli/commands/mcps.py +0 -1356
- glaip_sdk/cli/commands/models.py +0 -69
- glaip_sdk/cli/commands/tools.py +0 -576
- glaip_sdk/cli/commands/transcripts.py +0 -755
- glaip_sdk/cli/commands/update.py +0 -61
- glaip_sdk/cli/config.py +0 -95
- glaip_sdk/cli/constants.py +0 -38
- glaip_sdk/cli/context.py +0 -150
- glaip_sdk/cli/core/__init__.py +0 -79
- glaip_sdk/cli/core/context.py +0 -124
- glaip_sdk/cli/core/output.py +0 -846
- glaip_sdk/cli/core/prompting.py +0 -649
- glaip_sdk/cli/core/rendering.py +0 -187
- glaip_sdk/cli/display.py +0 -355
- glaip_sdk/cli/hints.py +0 -57
- glaip_sdk/cli/io.py +0 -112
- glaip_sdk/cli/main.py +0 -604
- glaip_sdk/cli/masking.py +0 -136
- glaip_sdk/cli/mcp_validators.py +0 -287
- glaip_sdk/cli/pager.py +0 -266
- glaip_sdk/cli/parsers/__init__.py +0 -7
- glaip_sdk/cli/parsers/json_input.py +0 -177
- glaip_sdk/cli/resolution.py +0 -67
- glaip_sdk/cli/rich_helpers.py +0 -27
- glaip_sdk/cli/slash/__init__.py +0 -15
- glaip_sdk/cli/slash/accounts_controller.py +0 -578
- glaip_sdk/cli/slash/accounts_shared.py +0 -75
- glaip_sdk/cli/slash/agent_session.py +0 -285
- glaip_sdk/cli/slash/prompt.py +0 -256
- glaip_sdk/cli/slash/remote_runs_controller.py +0 -566
- glaip_sdk/cli/slash/session.py +0 -1708
- glaip_sdk/cli/slash/tui/__init__.py +0 -9
- glaip_sdk/cli/slash/tui/accounts_app.py +0 -876
- glaip_sdk/cli/slash/tui/background_tasks.py +0 -72
- glaip_sdk/cli/slash/tui/loading.py +0 -58
- glaip_sdk/cli/slash/tui/remote_runs_app.py +0 -628
- glaip_sdk/cli/transcript/__init__.py +0 -31
- glaip_sdk/cli/transcript/cache.py +0 -536
- glaip_sdk/cli/transcript/capture.py +0 -329
- glaip_sdk/cli/transcript/export.py +0 -38
- glaip_sdk/cli/transcript/history.py +0 -815
- glaip_sdk/cli/transcript/launcher.py +0 -77
- glaip_sdk/cli/transcript/viewer.py +0 -374
- glaip_sdk/cli/update_notifier.py +0 -290
- glaip_sdk/cli/utils.py +0 -263
- glaip_sdk/cli/validators.py +0 -238
- glaip_sdk/client/__init__.py +0 -11
- glaip_sdk/client/_agent_payloads.py +0 -520
- glaip_sdk/client/agent_runs.py +0 -147
- glaip_sdk/client/agents.py +0 -1335
- glaip_sdk/client/base.py +0 -502
- glaip_sdk/client/main.py +0 -249
- glaip_sdk/client/mcps.py +0 -370
- glaip_sdk/client/run_rendering.py +0 -700
- glaip_sdk/client/shared.py +0 -21
- glaip_sdk/client/tools.py +0 -661
- glaip_sdk/client/validators.py +0 -198
- glaip_sdk/config/constants.py +0 -52
- glaip_sdk/mcps/__init__.py +0 -21
- glaip_sdk/mcps/base.py +0 -345
- glaip_sdk/models/__init__.py +0 -90
- glaip_sdk/models/agent.py +0 -47
- glaip_sdk/models/agent_runs.py +0 -116
- glaip_sdk/models/common.py +0 -42
- glaip_sdk/models/mcp.py +0 -33
- glaip_sdk/models/tool.py +0 -33
- glaip_sdk/payload_schemas/__init__.py +0 -7
- glaip_sdk/payload_schemas/agent.py +0 -85
- glaip_sdk/registry/__init__.py +0 -55
- glaip_sdk/registry/agent.py +0 -164
- glaip_sdk/registry/base.py +0 -139
- glaip_sdk/registry/mcp.py +0 -253
- glaip_sdk/registry/tool.py +0 -232
- glaip_sdk/runner/__init__.py +0 -59
- glaip_sdk/runner/base.py +0 -84
- glaip_sdk/runner/deps.py +0 -115
- glaip_sdk/runner/langgraph.py +0 -782
- glaip_sdk/runner/mcp_adapter/__init__.py +0 -13
- glaip_sdk/runner/mcp_adapter/base_mcp_adapter.py +0 -43
- glaip_sdk/runner/mcp_adapter/langchain_mcp_adapter.py +0 -257
- glaip_sdk/runner/mcp_adapter/mcp_config_builder.py +0 -95
- glaip_sdk/runner/tool_adapter/__init__.py +0 -18
- glaip_sdk/runner/tool_adapter/base_tool_adapter.py +0 -44
- glaip_sdk/runner/tool_adapter/langchain_tool_adapter.py +0 -219
- glaip_sdk/tools/__init__.py +0 -22
- glaip_sdk/tools/base.py +0 -435
- glaip_sdk/utils/__init__.py +0 -86
- glaip_sdk/utils/a2a/__init__.py +0 -34
- glaip_sdk/utils/a2a/event_processor.py +0 -188
- glaip_sdk/utils/agent_config.py +0 -194
- glaip_sdk/utils/bundler.py +0 -267
- glaip_sdk/utils/client.py +0 -111
- glaip_sdk/utils/client_utils.py +0 -486
- glaip_sdk/utils/datetime_helpers.py +0 -58
- glaip_sdk/utils/discovery.py +0 -78
- glaip_sdk/utils/display.py +0 -135
- glaip_sdk/utils/export.py +0 -143
- glaip_sdk/utils/general.py +0 -61
- glaip_sdk/utils/import_export.py +0 -168
- glaip_sdk/utils/import_resolver.py +0 -492
- glaip_sdk/utils/instructions.py +0 -101
- glaip_sdk/utils/rendering/__init__.py +0 -115
- glaip_sdk/utils/rendering/formatting.py +0 -264
- glaip_sdk/utils/rendering/layout/__init__.py +0 -64
- glaip_sdk/utils/rendering/layout/panels.py +0 -156
- glaip_sdk/utils/rendering/layout/progress.py +0 -202
- glaip_sdk/utils/rendering/layout/summary.py +0 -74
- glaip_sdk/utils/rendering/layout/transcript.py +0 -606
- glaip_sdk/utils/rendering/models.py +0 -85
- glaip_sdk/utils/rendering/renderer/__init__.py +0 -55
- glaip_sdk/utils/rendering/renderer/base.py +0 -1024
- glaip_sdk/utils/rendering/renderer/config.py +0 -27
- glaip_sdk/utils/rendering/renderer/console.py +0 -55
- glaip_sdk/utils/rendering/renderer/debug.py +0 -178
- glaip_sdk/utils/rendering/renderer/factory.py +0 -138
- glaip_sdk/utils/rendering/renderer/stream.py +0 -202
- glaip_sdk/utils/rendering/renderer/summary_window.py +0 -79
- glaip_sdk/utils/rendering/renderer/thinking.py +0 -273
- glaip_sdk/utils/rendering/renderer/toggle.py +0 -182
- glaip_sdk/utils/rendering/renderer/tool_panels.py +0 -442
- glaip_sdk/utils/rendering/renderer/transcript_mode.py +0 -162
- glaip_sdk/utils/rendering/state.py +0 -204
- glaip_sdk/utils/rendering/step_tree_state.py +0 -100
- glaip_sdk/utils/rendering/steps/__init__.py +0 -34
- glaip_sdk/utils/rendering/steps/event_processor.py +0 -778
- glaip_sdk/utils/rendering/steps/format.py +0 -176
- glaip_sdk/utils/rendering/steps/manager.py +0 -387
- glaip_sdk/utils/rendering/timing.py +0 -36
- glaip_sdk/utils/rendering/viewer/__init__.py +0 -21
- glaip_sdk/utils/rendering/viewer/presenter.py +0 -184
- glaip_sdk/utils/resource_refs.py +0 -195
- glaip_sdk/utils/run_renderer.py +0 -41
- glaip_sdk/utils/runtime_config.py +0 -425
- glaip_sdk/utils/serialization.py +0 -424
- glaip_sdk/utils/sync.py +0 -142
- glaip_sdk/utils/tool_detection.py +0 -33
- glaip_sdk/utils/validation.py +0 -264
- glaip_sdk-0.6.12.dist-info/RECORD +0 -159
- glaip_sdk-0.6.12.dist-info/entry_points.txt +0 -3
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
"""Renderer state utilities and helpers.
|
|
2
|
-
|
|
3
|
-
Authors:
|
|
4
|
-
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
|
|
9
|
-
import json
|
|
10
|
-
from dataclasses import dataclass, field
|
|
11
|
-
from datetime import datetime, timezone
|
|
12
|
-
from typing import Any
|
|
13
|
-
from collections.abc import Iterable
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def coerce_received_at(value: Any) -> datetime | None:
|
|
17
|
-
"""Coerce arbitrary values into timezone-aware datetimes if possible."""
|
|
18
|
-
if value is None:
|
|
19
|
-
return None
|
|
20
|
-
|
|
21
|
-
if isinstance(value, datetime):
|
|
22
|
-
return value if value.tzinfo else value.replace(tzinfo=timezone.utc)
|
|
23
|
-
|
|
24
|
-
if isinstance(value, str):
|
|
25
|
-
try:
|
|
26
|
-
normalised = value.replace("Z", "+00:00")
|
|
27
|
-
dt = datetime.fromisoformat(normalised)
|
|
28
|
-
except ValueError:
|
|
29
|
-
return None
|
|
30
|
-
return dt if dt.tzinfo else dt.replace(tzinfo=timezone.utc)
|
|
31
|
-
|
|
32
|
-
return None
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def truncate_display(text: str | None, limit: int = 160) -> str:
|
|
36
|
-
"""Return text capped at the given character limit with ellipsis."""
|
|
37
|
-
if not text:
|
|
38
|
-
return ""
|
|
39
|
-
stripped = str(text).strip()
|
|
40
|
-
if len(stripped) <= limit:
|
|
41
|
-
return stripped
|
|
42
|
-
return stripped[: limit - 1] + "…"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
@dataclass(slots=True)
|
|
46
|
-
class TranscriptBuffer:
|
|
47
|
-
"""Utility container for streaming transcript text."""
|
|
48
|
-
|
|
49
|
-
lines: list[str] = field(default_factory=list)
|
|
50
|
-
|
|
51
|
-
def append(self, value: str | None) -> None:
|
|
52
|
-
"""Append a chunk of transcript text."""
|
|
53
|
-
if not value:
|
|
54
|
-
return
|
|
55
|
-
self.lines.append(value)
|
|
56
|
-
|
|
57
|
-
def extend(self, chunks: Iterable[str]) -> None:
|
|
58
|
-
"""Append multiple chunks."""
|
|
59
|
-
for chunk in chunks:
|
|
60
|
-
self.append(chunk)
|
|
61
|
-
|
|
62
|
-
def clear(self) -> None:
|
|
63
|
-
"""Reset the buffer."""
|
|
64
|
-
self.lines.clear()
|
|
65
|
-
|
|
66
|
-
def render(self) -> str:
|
|
67
|
-
"""Return the concatenated transcript text."""
|
|
68
|
-
return "".join(self.lines)
|
|
69
|
-
|
|
70
|
-
def has_visible_text(self) -> bool:
|
|
71
|
-
"""Return True when any chunk contains non-whitespace characters."""
|
|
72
|
-
return any(chunk and chunk.strip() for chunk in self.lines)
|
|
73
|
-
|
|
74
|
-
def __bool__(self) -> bool:
|
|
75
|
-
"""Allow truthiness checks like a regular list."""
|
|
76
|
-
return bool(self.lines)
|
|
77
|
-
|
|
78
|
-
def __len__(self) -> int:
|
|
79
|
-
"""Return buffered chunk count."""
|
|
80
|
-
return len(self.lines)
|
|
81
|
-
|
|
82
|
-
def __iter__(self):
|
|
83
|
-
"""Iterate over buffered chunks."""
|
|
84
|
-
return iter(self.lines)
|
|
85
|
-
|
|
86
|
-
def __getitem__(self, index: int) -> str:
|
|
87
|
-
"""Return the chunk at the requested index."""
|
|
88
|
-
return self.lines[index]
|
|
89
|
-
|
|
90
|
-
def __contains__(self, item: object) -> bool:
|
|
91
|
-
"""Membership test for convenience."""
|
|
92
|
-
return item in self.lines
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
@dataclass
|
|
96
|
-
class RendererState:
|
|
97
|
-
"""Internal state for the renderer."""
|
|
98
|
-
|
|
99
|
-
buffer: TranscriptBuffer = field(default_factory=TranscriptBuffer)
|
|
100
|
-
final_text: str = ""
|
|
101
|
-
streaming_started_at: float | None = None
|
|
102
|
-
printed_final_output: bool = False
|
|
103
|
-
finalizing_ui: bool = False
|
|
104
|
-
final_duration_seconds: float | None = None
|
|
105
|
-
final_duration_text: str | None = None
|
|
106
|
-
events: list[dict[str, Any]] = field(default_factory=list)
|
|
107
|
-
meta: dict[str, Any] = field(default_factory=dict)
|
|
108
|
-
streaming_started_event_ts: datetime | None = None
|
|
109
|
-
|
|
110
|
-
def record_event(self, event: dict[str, Any], *, received_at: datetime | None = None) -> None:
|
|
111
|
-
"""Capture an event snapshot for transcript replay."""
|
|
112
|
-
try:
|
|
113
|
-
captured = json.loads(json.dumps(event))
|
|
114
|
-
except Exception:
|
|
115
|
-
captured = dict(event)
|
|
116
|
-
|
|
117
|
-
if received_at is not None:
|
|
118
|
-
try:
|
|
119
|
-
captured["received_at"] = received_at.isoformat()
|
|
120
|
-
except Exception:
|
|
121
|
-
try:
|
|
122
|
-
captured["received_at"] = str(received_at)
|
|
123
|
-
except Exception:
|
|
124
|
-
captured["received_at"] = repr(received_at)
|
|
125
|
-
|
|
126
|
-
self.events.append(captured)
|
|
127
|
-
|
|
128
|
-
def set_final_output(self, value: str) -> None:
|
|
129
|
-
"""Record the final assistant output."""
|
|
130
|
-
self.final_text = value
|
|
131
|
-
|
|
132
|
-
def append_transcript_text(self, value: str) -> None:
|
|
133
|
-
"""Append streaming text to the transcript buffer."""
|
|
134
|
-
self.buffer.append(value)
|
|
135
|
-
|
|
136
|
-
def start_stream_timer(self, now: float | None) -> None:
|
|
137
|
-
"""Record start timestamp when streaming begins."""
|
|
138
|
-
if now is None or self.streaming_started_at is not None:
|
|
139
|
-
return
|
|
140
|
-
self.streaming_started_at = now
|
|
141
|
-
|
|
142
|
-
def stop_stream_timer(self, now: float | None) -> float | None:
|
|
143
|
-
"""Record the total elapsed duration."""
|
|
144
|
-
if now is None or self.streaming_started_at is None:
|
|
145
|
-
return None
|
|
146
|
-
duration = max(0.0, now - self.streaming_started_at)
|
|
147
|
-
self.final_duration_seconds = duration
|
|
148
|
-
return duration
|
|
149
|
-
|
|
150
|
-
def mark_final_duration(self, duration: float | None, *, formatted: str | None = None) -> None:
|
|
151
|
-
"""Store the final duration metadata."""
|
|
152
|
-
if duration is not None:
|
|
153
|
-
self.final_duration_seconds = duration
|
|
154
|
-
self.final_duration_text = formatted
|
|
155
|
-
|
|
156
|
-
def to_snapshot(self) -> dict[str, Any]:
|
|
157
|
-
"""Return a serialisable snapshot for presenters."""
|
|
158
|
-
return prepare_transcript_snapshot(self)
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
@dataclass
|
|
162
|
-
class ThinkingScopeState:
|
|
163
|
-
"""Runtime bookkeeping for deterministic thinking spans."""
|
|
164
|
-
|
|
165
|
-
anchor_id: str
|
|
166
|
-
task_id: str | None
|
|
167
|
-
context_id: str | None
|
|
168
|
-
anchor_started_at: float | None = None
|
|
169
|
-
anchor_finished_at: float | None = None
|
|
170
|
-
idle_started_at: float | None = None
|
|
171
|
-
idle_started_monotonic: float | None = None
|
|
172
|
-
active_thinking_id: str | None = None
|
|
173
|
-
running_children: set[str] = field(default_factory=set)
|
|
174
|
-
closed: bool = False
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
def accumulate_final_text(*, state: RendererState) -> str:
|
|
178
|
-
"""Return the most relevant final text for summary panels."""
|
|
179
|
-
if state.final_text.strip():
|
|
180
|
-
return state.final_text.strip()
|
|
181
|
-
return state.buffer.render().strip()
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
def prepare_transcript_snapshot(state: RendererState) -> dict[str, Any]:
|
|
185
|
-
"""Return a dictionary capturing renderer transcript state."""
|
|
186
|
-
return {
|
|
187
|
-
"final_text": state.final_text,
|
|
188
|
-
"buffer_text": state.buffer.render(),
|
|
189
|
-
"events": list(state.events),
|
|
190
|
-
"meta": dict(state.meta),
|
|
191
|
-
"final_duration_seconds": state.final_duration_seconds,
|
|
192
|
-
"final_duration_text": state.final_duration_text,
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
__all__ = [
|
|
197
|
-
"RendererState",
|
|
198
|
-
"ThinkingScopeState",
|
|
199
|
-
"TranscriptBuffer",
|
|
200
|
-
"accumulate_final_text",
|
|
201
|
-
"coerce_received_at",
|
|
202
|
-
"prepare_transcript_snapshot",
|
|
203
|
-
"truncate_display",
|
|
204
|
-
]
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
"""State container for hierarchical renderer steps.
|
|
2
|
-
|
|
3
|
-
Authors:
|
|
4
|
-
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
|
|
9
|
-
from collections.abc import Iterator
|
|
10
|
-
from dataclasses import dataclass, field
|
|
11
|
-
|
|
12
|
-
from glaip_sdk.utils.rendering.models import Step
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@dataclass(slots=True)
|
|
16
|
-
class StepTreeState:
|
|
17
|
-
"""Track hierarchical ordering, buffers, and pruning metadata."""
|
|
18
|
-
|
|
19
|
-
max_steps: int = 200
|
|
20
|
-
root_order: list[str] = field(default_factory=list)
|
|
21
|
-
child_map: dict[str, list[str]] = field(default_factory=dict)
|
|
22
|
-
buffered_children: dict[str, list[str]] = field(default_factory=dict)
|
|
23
|
-
running_by_context: dict[tuple[str | None, str | None], set[str]] = field(default_factory=dict)
|
|
24
|
-
retained_ids: set[str] = field(default_factory=set)
|
|
25
|
-
step_index: dict[str, Step] = field(default_factory=dict)
|
|
26
|
-
pending_branch_failures: set[str] = field(default_factory=set)
|
|
27
|
-
|
|
28
|
-
def link_root(self, step_id: str) -> None:
|
|
29
|
-
"""Ensure a step id is present in the root ordering."""
|
|
30
|
-
if step_id not in self.root_order:
|
|
31
|
-
self.root_order.append(step_id)
|
|
32
|
-
|
|
33
|
-
def unlink_root(self, step_id: str) -> None:
|
|
34
|
-
"""Remove a step id from the root ordering if present."""
|
|
35
|
-
if step_id in self.root_order:
|
|
36
|
-
self.root_order.remove(step_id)
|
|
37
|
-
|
|
38
|
-
def link_child(self, parent_id: str, child_id: str) -> None:
|
|
39
|
-
"""Attach a child step to a parent."""
|
|
40
|
-
children = self.child_map.setdefault(parent_id, [])
|
|
41
|
-
if child_id not in children:
|
|
42
|
-
children.append(child_id)
|
|
43
|
-
|
|
44
|
-
def unlink_child(self, parent_id: str, child_id: str) -> None:
|
|
45
|
-
"""Detach a child from a parent."""
|
|
46
|
-
children = self.child_map.get(parent_id)
|
|
47
|
-
if not children:
|
|
48
|
-
return
|
|
49
|
-
|
|
50
|
-
if child_id in children:
|
|
51
|
-
children.remove(child_id)
|
|
52
|
-
# Clean up if the list is now empty
|
|
53
|
-
if len(children) == 0:
|
|
54
|
-
self.child_map.pop(parent_id, None)
|
|
55
|
-
|
|
56
|
-
def buffer_child(self, parent_id: str, child_id: str) -> None:
|
|
57
|
-
"""Track a child that is waiting for its parent to appear."""
|
|
58
|
-
queue = self.buffered_children.setdefault(parent_id, [])
|
|
59
|
-
if child_id not in queue:
|
|
60
|
-
queue.append(child_id)
|
|
61
|
-
|
|
62
|
-
def pop_buffered_children(self, parent_id: str) -> list[str]:
|
|
63
|
-
"""Return any buffered children for a parent."""
|
|
64
|
-
return self.buffered_children.pop(parent_id, [])
|
|
65
|
-
|
|
66
|
-
def discard_running(self, step_id: str) -> None:
|
|
67
|
-
"""Remove a step from running context tracking."""
|
|
68
|
-
for key, running in tuple(self.running_by_context.items()):
|
|
69
|
-
if step_id in running:
|
|
70
|
-
running.discard(step_id)
|
|
71
|
-
if not running:
|
|
72
|
-
self.running_by_context.pop(key, None)
|
|
73
|
-
|
|
74
|
-
def iter_visible_tree(self) -> Iterator[tuple[str, tuple[bool, ...]]]:
|
|
75
|
-
"""Yield step ids in depth-first order alongside branch metadata.
|
|
76
|
-
|
|
77
|
-
Returns:
|
|
78
|
-
Iterator of (step_id, branch_state) tuples where branch_state
|
|
79
|
-
captures whether each ancestor was the last child. This data
|
|
80
|
-
is later used by rendering helpers to draw connectors such as
|
|
81
|
-
`│`, `├─`, and `└─` consistently.
|
|
82
|
-
"""
|
|
83
|
-
roots = tuple(self.root_order)
|
|
84
|
-
total_roots = len(roots)
|
|
85
|
-
for index, root_id in enumerate(roots):
|
|
86
|
-
yield root_id, ()
|
|
87
|
-
ancestor_state = (index == total_roots - 1,)
|
|
88
|
-
yield from self._walk_children(root_id, ancestor_state)
|
|
89
|
-
|
|
90
|
-
def _walk_children(
|
|
91
|
-
self, parent_id: str, ancestor_state: tuple[bool, ...]
|
|
92
|
-
) -> Iterator[tuple[str, tuple[bool, ...]]]:
|
|
93
|
-
"""Depth-first traversal helper yielding children with ancestry info."""
|
|
94
|
-
children = self.child_map.get(parent_id, [])
|
|
95
|
-
total_children = len(children)
|
|
96
|
-
for idx, child_id in enumerate(children):
|
|
97
|
-
is_last = idx == total_children - 1
|
|
98
|
-
branch_state = ancestor_state + (is_last,)
|
|
99
|
-
yield child_id, branch_state
|
|
100
|
-
yield from self._walk_children(child_id, branch_state)
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
"""Step management and presentation helpers."""
|
|
2
|
-
|
|
3
|
-
from glaip_sdk.utils.rendering.steps.format import (
|
|
4
|
-
UNKNOWN_STEP_DETAIL,
|
|
5
|
-
STATUS_ICON_STYLES,
|
|
6
|
-
StepPresentation,
|
|
7
|
-
build_connector_prefix,
|
|
8
|
-
compose_display_label,
|
|
9
|
-
format_step,
|
|
10
|
-
format_step_label,
|
|
11
|
-
format_tool_args,
|
|
12
|
-
humanize_tool_name,
|
|
13
|
-
resolve_label_body,
|
|
14
|
-
status_icon_for_step,
|
|
15
|
-
step_icon_for_kind,
|
|
16
|
-
)
|
|
17
|
-
from glaip_sdk.utils.rendering.steps.manager import StepManager, StepManagerError
|
|
18
|
-
|
|
19
|
-
__all__ = [
|
|
20
|
-
"StepManager",
|
|
21
|
-
"StepManagerError",
|
|
22
|
-
"UNKNOWN_STEP_DETAIL",
|
|
23
|
-
"STATUS_ICON_STYLES",
|
|
24
|
-
"StepPresentation",
|
|
25
|
-
"build_connector_prefix",
|
|
26
|
-
"compose_display_label",
|
|
27
|
-
"format_step",
|
|
28
|
-
"format_step_label",
|
|
29
|
-
"format_tool_args",
|
|
30
|
-
"humanize_tool_name",
|
|
31
|
-
"resolve_label_body",
|
|
32
|
-
"status_icon_for_step",
|
|
33
|
-
"step_icon_for_kind",
|
|
34
|
-
]
|