glaip-sdk 0.1.2__py3-none-any.whl → 0.6.5b3__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 +9 -0
- glaip_sdk/agents/__init__.py +27 -0
- glaip_sdk/agents/base.py +1090 -0
- glaip_sdk/branding.py +13 -0
- glaip_sdk/cli/account_store.py +540 -0
- glaip_sdk/cli/auth.py +254 -15
- glaip_sdk/cli/commands/__init__.py +2 -2
- glaip_sdk/cli/commands/accounts.py +746 -0
- glaip_sdk/cli/commands/agents.py +214 -74
- glaip_sdk/cli/commands/common_config.py +101 -0
- glaip_sdk/cli/commands/configure.py +729 -113
- glaip_sdk/cli/commands/mcps.py +241 -72
- glaip_sdk/cli/commands/models.py +11 -5
- glaip_sdk/cli/commands/tools.py +49 -57
- glaip_sdk/cli/commands/transcripts.py +755 -0
- glaip_sdk/cli/config.py +48 -4
- 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 +41 -20
- glaip_sdk/cli/hints.py +57 -0
- glaip_sdk/cli/io.py +6 -3
- glaip_sdk/cli/main.py +228 -119
- glaip_sdk/cli/masking.py +21 -33
- glaip_sdk/cli/pager.py +9 -10
- glaip_sdk/cli/parsers/__init__.py +1 -3
- glaip_sdk/cli/slash/__init__.py +0 -9
- glaip_sdk/cli/slash/accounts_controller.py +500 -0
- glaip_sdk/cli/slash/accounts_shared.py +75 -0
- glaip_sdk/cli/slash/agent_session.py +58 -20
- glaip_sdk/cli/slash/prompt.py +10 -0
- glaip_sdk/cli/slash/remote_runs_controller.py +566 -0
- glaip_sdk/cli/slash/session.py +736 -134
- 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 +872 -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 +255 -44
- glaip_sdk/cli/transcript/capture.py +66 -1
- glaip_sdk/cli/transcript/history.py +815 -0
- glaip_sdk/cli/transcript/viewer.py +70 -463
- glaip_sdk/cli/update_notifier.py +14 -5
- glaip_sdk/cli/utils.py +243 -1258
- glaip_sdk/cli/validators.py +5 -6
- glaip_sdk/client/__init__.py +2 -1
- glaip_sdk/client/_agent_payloads.py +45 -9
- glaip_sdk/client/agent_runs.py +147 -0
- glaip_sdk/client/agents.py +287 -29
- glaip_sdk/client/base.py +1 -0
- glaip_sdk/client/main.py +19 -10
- glaip_sdk/client/mcps.py +122 -12
- glaip_sdk/client/run_rendering.py +133 -90
- glaip_sdk/client/shared.py +21 -0
- glaip_sdk/client/tools.py +153 -10
- glaip_sdk/config/constants.py +11 -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 +1 -13
- 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 +238 -0
- glaip_sdk/rich_components.py +58 -2
- glaip_sdk/tools/__init__.py +22 -0
- glaip_sdk/tools/base.py +435 -0
- glaip_sdk/utils/__init__.py +58 -12
- glaip_sdk/utils/bundler.py +267 -0
- glaip_sdk/utils/client.py +111 -0
- glaip_sdk/utils/client_utils.py +39 -7
- glaip_sdk/utils/datetime_helpers.py +58 -0
- glaip_sdk/utils/discovery.py +78 -0
- glaip_sdk/utils/display.py +23 -15
- glaip_sdk/utils/export.py +143 -0
- glaip_sdk/utils/general.py +0 -33
- glaip_sdk/utils/import_export.py +12 -7
- 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 +5 -30
- glaip_sdk/utils/rendering/layout/__init__.py +64 -0
- glaip_sdk/utils/rendering/{renderer → layout}/panels.py +9 -0
- glaip_sdk/utils/rendering/{renderer → layout}/progress.py +70 -1
- glaip_sdk/utils/rendering/layout/summary.py +74 -0
- glaip_sdk/utils/rendering/layout/transcript.py +606 -0
- glaip_sdk/utils/rendering/models.py +1 -0
- glaip_sdk/utils/rendering/renderer/__init__.py +9 -47
- glaip_sdk/utils/rendering/renderer/base.py +241 -1434
- glaip_sdk/utils/rendering/renderer/config.py +1 -5
- glaip_sdk/utils/rendering/renderer/debug.py +26 -20
- glaip_sdk/utils/rendering/renderer/factory.py +138 -0
- glaip_sdk/utils/rendering/renderer/stream.py +4 -33
- glaip_sdk/utils/rendering/renderer/summary_window.py +79 -0
- glaip_sdk/utils/rendering/renderer/thinking.py +273 -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/steps/__init__.py +34 -0
- glaip_sdk/utils/rendering/{steps.py → steps/event_processor.py} +53 -440
- 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 +25 -13
- glaip_sdk/utils/runtime_config.py +306 -0
- glaip_sdk/utils/serialization.py +18 -0
- glaip_sdk/utils/sync.py +142 -0
- glaip_sdk/utils/validation.py +16 -24
- {glaip_sdk-0.1.2.dist-info → glaip_sdk-0.6.5b3.dist-info}/METADATA +39 -4
- glaip_sdk-0.6.5b3.dist-info/RECORD +145 -0
- {glaip_sdk-0.1.2.dist-info → glaip_sdk-0.6.5b3.dist-info}/WHEEL +1 -1
- glaip_sdk/models.py +0 -240
- glaip_sdk-0.1.2.dist-info/RECORD +0 -82
- {glaip_sdk-0.1.2.dist-info → glaip_sdk-0.6.5b3.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Export utilities for remote agent run transcripts.
|
|
3
|
+
|
|
4
|
+
Authors:
|
|
5
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import json
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from glaip_sdk.models.agent_runs import RunWithOutput, RunOutputChunk
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def export_remote_transcript_jsonl(
|
|
17
|
+
run: RunWithOutput,
|
|
18
|
+
destination: Path,
|
|
19
|
+
*,
|
|
20
|
+
overwrite: bool = False,
|
|
21
|
+
agent_name: str | None = None,
|
|
22
|
+
model: str | None = None,
|
|
23
|
+
) -> Path:
|
|
24
|
+
"""Export a remote run transcript to JSONL format compatible with local transcript viewers.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
run: RunWithOutput instance to export
|
|
28
|
+
destination: Target file path for JSONL export
|
|
29
|
+
overwrite: Whether to overwrite existing file
|
|
30
|
+
agent_name: Optional agent name for metadata
|
|
31
|
+
model: Optional model name for metadata (extracted from run.config if not provided)
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
Path to the exported file
|
|
35
|
+
|
|
36
|
+
Raises:
|
|
37
|
+
FileExistsError: If destination exists and overwrite is False
|
|
38
|
+
OSError: If file cannot be written
|
|
39
|
+
"""
|
|
40
|
+
if destination.exists() and not overwrite:
|
|
41
|
+
raise FileExistsError(f"File already exists: {destination}")
|
|
42
|
+
|
|
43
|
+
# Ensure parent directory exists
|
|
44
|
+
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
45
|
+
|
|
46
|
+
model_name = model or _extract_model(run)
|
|
47
|
+
final_output_text = _extract_final_output(run.output) or ""
|
|
48
|
+
|
|
49
|
+
meta_payload = _build_meta_payload(run, agent_name, model_name)
|
|
50
|
+
meta_record = _build_meta_record(run, agent_name, model_name, final_output_text, meta_payload)
|
|
51
|
+
|
|
52
|
+
_write_jsonl_file(destination, meta_record, run.output)
|
|
53
|
+
|
|
54
|
+
return destination
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _build_meta_payload(run: RunWithOutput, agent_name: str | None, model_name: str | None) -> dict[str, Any]:
|
|
58
|
+
"""Build the meta payload dictionary."""
|
|
59
|
+
return {
|
|
60
|
+
"agent_name": agent_name,
|
|
61
|
+
"model": model_name,
|
|
62
|
+
"input_message": run.input,
|
|
63
|
+
"status": run.status,
|
|
64
|
+
"run_type": run.run_type,
|
|
65
|
+
"schedule_id": str(run.schedule_id) if run.schedule_id else None,
|
|
66
|
+
"config": run.config or {},
|
|
67
|
+
"created_at": run.created_at.isoformat() if run.created_at else None,
|
|
68
|
+
"updated_at": run.updated_at.isoformat() if run.updated_at else None,
|
|
69
|
+
"event_count": len(run.output),
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _build_meta_record(
|
|
74
|
+
run: RunWithOutput,
|
|
75
|
+
agent_name: str | None,
|
|
76
|
+
model_name: str | None,
|
|
77
|
+
final_output_text: str,
|
|
78
|
+
meta_payload: dict[str, Any],
|
|
79
|
+
) -> dict[str, Any]:
|
|
80
|
+
"""Build the meta record dictionary."""
|
|
81
|
+
return {
|
|
82
|
+
"type": "meta",
|
|
83
|
+
"run_id": str(run.id),
|
|
84
|
+
"agent_id": str(run.agent_id),
|
|
85
|
+
"agent_name": agent_name,
|
|
86
|
+
"model": model_name,
|
|
87
|
+
"created_at": run.created_at.isoformat() if run.created_at else None,
|
|
88
|
+
"default_output": final_output_text,
|
|
89
|
+
"final_output": final_output_text,
|
|
90
|
+
"server_run_id": str(run.id),
|
|
91
|
+
"started_at": run.started_at.isoformat() if run.started_at else None,
|
|
92
|
+
"finished_at": run.completed_at.isoformat() if run.completed_at else None,
|
|
93
|
+
"meta": meta_payload,
|
|
94
|
+
"source": "remote_history",
|
|
95
|
+
# Back-compat fields used by older tooling
|
|
96
|
+
"run_type": run.run_type,
|
|
97
|
+
"schedule_id": str(run.schedule_id) if run.schedule_id else None,
|
|
98
|
+
"status": run.status,
|
|
99
|
+
"input": run.input,
|
|
100
|
+
"config": run.config or {},
|
|
101
|
+
"updated_at": run.updated_at.isoformat() if run.updated_at else None,
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _write_jsonl_file(destination: Path, meta_record: dict[str, Any], events: list[RunOutputChunk]) -> None:
|
|
106
|
+
"""Write the JSONL file with meta and event records."""
|
|
107
|
+
records: list[dict[str, Any]] = [meta_record]
|
|
108
|
+
records.extend({"type": "event", "event": event} for event in events)
|
|
109
|
+
|
|
110
|
+
with destination.open("w", encoding="utf-8") as fh:
|
|
111
|
+
for idx, record in enumerate(records):
|
|
112
|
+
json.dump(record, fh, ensure_ascii=False, indent=2, default=_json_default)
|
|
113
|
+
fh.write("\n")
|
|
114
|
+
if idx != len(records) - 1:
|
|
115
|
+
fh.write("\n")
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _extract_model(run: RunWithOutput) -> str | None:
|
|
119
|
+
"""Best-effort extraction of the model name from run metadata."""
|
|
120
|
+
config = run.config or {}
|
|
121
|
+
if isinstance(config, dict):
|
|
122
|
+
model = config.get("model") or config.get("llm", {}).get("model")
|
|
123
|
+
if isinstance(model, str):
|
|
124
|
+
return model
|
|
125
|
+
return None
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def _extract_final_output(events: list[RunOutputChunk]) -> str | None:
|
|
129
|
+
"""Return the final response content from the event stream."""
|
|
130
|
+
for chunk in reversed(events):
|
|
131
|
+
content = chunk.get("content")
|
|
132
|
+
if not content:
|
|
133
|
+
continue
|
|
134
|
+
if chunk.get("event_type") == "final_response" or chunk.get("final"):
|
|
135
|
+
return str(content)
|
|
136
|
+
return None
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def _json_default(obj: Any) -> Any:
|
|
140
|
+
"""JSON serializer for datetime objects."""
|
|
141
|
+
if isinstance(obj, datetime):
|
|
142
|
+
return obj.isoformat()
|
|
143
|
+
raise TypeError(f"Type {type(obj)} not serializable")
|
glaip_sdk/utils/general.py
CHANGED
|
@@ -4,46 +4,13 @@ Authors:
|
|
|
4
4
|
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
import re
|
|
8
7
|
from collections.abc import Iterable, Iterator
|
|
9
8
|
from datetime import datetime
|
|
10
9
|
from typing import Any
|
|
11
|
-
from uuid import UUID
|
|
12
10
|
|
|
13
11
|
import click
|
|
14
12
|
|
|
15
13
|
|
|
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 sanitize_name(name: str) -> str:
|
|
33
|
-
"""Sanitize a name for resource creation.
|
|
34
|
-
|
|
35
|
-
Args:
|
|
36
|
-
name: Raw name input
|
|
37
|
-
|
|
38
|
-
Returns:
|
|
39
|
-
Sanitized name suitable for resource creation
|
|
40
|
-
"""
|
|
41
|
-
# Remove special characters and normalize
|
|
42
|
-
sanitized = re.sub(r"[^a-zA-Z0-9\-_]", "-", name.strip())
|
|
43
|
-
sanitized = re.sub(r"-+", "-", sanitized) # Collapse multiple dashes
|
|
44
|
-
return sanitized.lower().strip("-")
|
|
45
|
-
|
|
46
|
-
|
|
47
14
|
def format_file_size(size_bytes: int) -> str:
|
|
48
15
|
"""Format file size in human readable format.
|
|
49
16
|
|
glaip_sdk/utils/import_export.py
CHANGED
|
@@ -9,10 +9,19 @@ Authors:
|
|
|
9
9
|
|
|
10
10
|
from typing import Any
|
|
11
11
|
|
|
12
|
+
from glaip_sdk.utils.resource_refs import _extract_id_from_item
|
|
13
|
+
|
|
12
14
|
|
|
13
15
|
def extract_ids_from_export(items: list[Any]) -> list[str]:
|
|
14
16
|
"""Extract IDs from export format (list of dicts with id/name fields).
|
|
15
17
|
|
|
18
|
+
This function is similar to `extract_ids` in `resource_refs.py` but differs in behavior:
|
|
19
|
+
- This function SKIPS items without IDs (doesn't convert to string)
|
|
20
|
+
- `extract_ids` converts items without IDs to strings as fallback
|
|
21
|
+
|
|
22
|
+
This difference is intentional: export format should only include actual IDs,
|
|
23
|
+
while general resource reference extraction may need fallback string conversion.
|
|
24
|
+
|
|
16
25
|
Args:
|
|
17
26
|
items: List of items (dicts with id/name or strings)
|
|
18
27
|
|
|
@@ -29,13 +38,9 @@ def extract_ids_from_export(items: list[Any]) -> list[str]:
|
|
|
29
38
|
|
|
30
39
|
ids = []
|
|
31
40
|
for item in items:
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
ids.append(str(item.id))
|
|
36
|
-
elif isinstance(item, dict) and "id" in item:
|
|
37
|
-
ids.append(str(item["id"]))
|
|
38
|
-
# Skip items without ID (don't convert to string)
|
|
41
|
+
extracted = _extract_id_from_item(item, skip_missing=True)
|
|
42
|
+
if extracted is not None:
|
|
43
|
+
ids.append(extracted)
|
|
39
44
|
|
|
40
45
|
return ids
|
|
41
46
|
|