Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,10 @@ not the main API documentation contract.
| `tests/` | pytest 9, xdist, respx, socket blocking, timeout and coverage plugins |
| `splunk-ao-a2a/` | Independently released native-OTel A2A instrumentation; uv/Hatch |
| `splunk-ao-adk/` | Independently released Google ADK handler integration; uv/Hatch |
| `splunk-ao-migration-tool/` | Migration documentation and examples, not a buildable package |
| `splunk-ao-migration-tool/` | uv workspace; `splunk-ao-migrate` CLI built from `splunk_ao_migrate/pyproject.toml` |
| `src/splunk_ao/resources/` | OpenAPI-generated transport client; never hand-edit |

The three buildable packages have independent versions, CI, and release workflows. Only the root `poetry.lock` is
The four buildable packages have independent versions, CI, and release workflows. Only the root `poetry.lock` is
tracked; A2A/ADK `uv.lock` files are ignored and may be created locally by uv. Validate every package a change touches.
CI supports Python 3.11–3.14; root CI also spans Linux, macOS, and Windows.

Expand Down
5 changes: 3 additions & 2 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@ referenced code and tests; code remains authoritative.

## Repository Topology

The repository contains three independently built and released packages:
The repository contains four independently built and released packages:

| Package | Source | Purpose | Tooling |
|---|---|---|---|
| `splunk-ao` | `src/splunk_ao/` | Core API, logging, integrations, CRUD, OTLP export | Poetry |
| `splunk-ao-a2a` | `splunk-ao-a2a/src/splunk_ao_a2a/` | A2A client/server native OTel instrumentation | uv/Hatch |
| `splunk-ao-adk` | `splunk-ao-adk/src/splunk_ao_adk/` | Google ADK handler/plugin integration | uv/Hatch |
| `splunk-ao-migrate` | `splunk-ao-migration-tool/splunk_ao_migrate/src/splunk_ao_migrate/` | galileo → splunk-ao migration CLI | uv/Hatch |

`splunk-ao-migration-tool/` currently contains migration documentation and examples. `docs/` contains repository
`splunk-ao-migration-tool/` is a uv workspace; `splunk_ao_migrate/pyproject.toml` defines the `splunk-ao-migrate` package. `docs/` contains repository
documentation; generated API references are produced by `scripts/create_docs.py`.

## Core SDK Layers
Expand Down
13 changes: 13 additions & 0 deletions splunk-ao-migration-tool/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Workspace root — not a buildable package itself.
# Run `uv sync --dev` here to get both packages and their dev deps.
# Run `uv run pytest` here to execute all tests across the workspace.

[tool.uv.workspace]
members = [
"splunk_ao_migrate",
]

[tool.pytest.ini_options]
testpaths = [
"splunk_ao_migrate/tests",
]
192 changes: 192 additions & 0 deletions splunk-ao-migration-tool/splunk_ao_migrate/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
# splunk_ao_migrate — Regex-Based Migration Tool

Automatically migrate Python code from the `galileo` SDK to `splunk-ao-python`
using ordered regex substitutions.

## What it does

Rewrites every file type the migration touches in a single pass, then renames any
directories or files whose names contain `galileo`:

| File type | Examples | What changes |
|-----------|----------|--------------|
| Python source | `*.py` | Imports, class names, kwargs, env-var strings, HTTP headers |
| Doc files | `*.md`, `*.rst` | Same rules as Python; known Galileo doc URLs rewritten to Splunk AO equivalents; all other URLs left intact |
| Dependency files | `requirements*.txt`, `pyproject.toml` | Package names, Python identifiers, uv source keys, pytest env vars, brand prose, `requires-python` floor |
| Environment files | `.env`, `.env.example` | All `GALILEO_*` keys → `SPLUNK_AO_*`; `galileo` in placeholder values |
| Filesystem paths | directories, filenames | `galileo-a2a/` → `splunk-ao-a2a/`, `galileo_a2a/` → `splunk_ao_a2a/`, etc. |

## Installation

```bash
# Install from the package directory
pip install ./splunk_ao_migrate

# Or with uv
uv pip install ./splunk_ao_migrate
```

> Run from `splunk-ao-migration-tool/` (the workspace root).

No external dependencies — uses Python stdlib only.

## Usage

```bash
# Rewrite an entire directory in place
splunk-ao-migrate src/

# Rewrite a single file
splunk-ao-migrate my_agent.py

# Preview changes without writing (dry run)
splunk-ao-migrate --dry-run src/

# Suppress the summary report
splunk-ao-migrate --no-report src/

# Run directly without installing (from the workspace root)
python splunk_ao_migrate/src/splunk_ao_migrate/migrate.py --dry-run src/

# Run as a module (after uv sync)
python -m splunk_ao_migrate.migrate --dry-run src/

# Run with uv (from the workspace root)
uv run python splunk_ao_migrate/src/splunk_ao_migrate/migrate.py --dry-run src/
```

## Package layout

```
splunk_ao_migrate/ ← package root (uv workspace member)
pyproject.toml ← package metadata and entry point declaration
README.md ← this file
src/
splunk_ao_migrate/ ← Python package (src layout)
migrate.py ← CLI entry point (splunk-ao-migrate console script)
rules.py ← all substitution rules (imports, symbols, kwargs, env-vars, headers)
transformer.py ← applies rules to source text, returns TransformResult
reporter.py ← formats and prints the migration summary report
```
Comment thread
ridhima-splunk marked this conversation as resolved.

## What gets migrated

### Python files

- `from galileo import …` → `from splunk_ao import …`
- `from galileo.metric import …` → `from splunk_ao.evaluator import …`
- `GalileoLogger` → `SplunkAOLogger` (and all other `Galileo*` class renames)
- `GalileoMetric` / `GalileoMetrics` / `GalileoScorers` → `SplunkAOEvaluator` / `SplunkAOEvaluators`
- `SplunkAOMetric` → `SplunkAOEvaluator`, `SplunkAOMetrics` → `SplunkAOEvaluators`
- Domain renames: `Metric` → `Evaluator`, `LlmMetric` → `LlmEvaluator`, `LocalMetric` → `LocalEvaluator`, etc.
- **Not renamed**: `MetricSpec` and `LocalMetricConfig` — these remain as live names in `splunk-ao` (the rename proposal `EvaluatorSpec` / `LocalEvaluatorConfig` was not implemented)
- `LogStream` → `AgentStream`, `.logstreams` → `.agent_streams`
- Method renames: `get_log_stream` → `get_agent_stream`, `create_log_stream` → `create_agent_stream`, `list_log_streams` → `list_agent_streams`, `delete_metric` → `delete_evaluator`, `create_custom_llm_metric` → `create_custom_llm_evaluator`
- **Not renamed**: `get_metrics()` and `set_metrics()` on `AgentStream` — these remain as live method names; only the module-level `get_evaluators()` function is the new API
- Keyword argument and parameter renames: `log_stream=` → `agent_stream=`, `log_stream_name=` → `agent_stream_name=`, `logstream=` → `agentstream=`; also catches typed parameter declarations like `log_stream: str | None = None` → `agent_stream: str | None = None`
- Config file renames: `galileo-python-config.json` → `splunk-ao-config.json`, `galileo-config.json` → `splunk-ao-config.json`
- `GALILEO_*` env-var string literals → `SPLUNK_AO_*` (e.g. `GALILEO_API_KEY`, `GALILEO_API_ENDPOINT`, `GALILEO_CONSOLE_URL`, `GALILEO_HOME_DIR`)
- `X-Galileo-Trace-ID` / `X-Galileo-Parent-ID` HTTP headers
- `GalileoSpanProcessor` → `SplunkAOSpanProcessor`, `add_galileo_span_processor` → `add_splunk_ao_span_processor`
- `GalileoObserver` → `SplunkAOObserver`
- `galileo_*` prefixed identifiers (e.g. `galileo_session_id`) → `splunk_ao_*`
- `_galileo_` mid-identifier and attribute patterns (e.g. `func._galileo_is_retriever`, `self._handler._galileo_logger`) → `_splunk_ao_*`; the rule fires after `.`, spaces, and quotes, not just within word characters
- `GALILEO_OBSERVE_KEY` constant name → `SPLUNK_AO_OBSERVE_KEY`; the string wire value `"galileo_observe"` → `"splunk_ao_observe"` (used as the A2A metadata key in `splunk-ao-a2a`)
- `galileo-a2a` package name in string literals and pip installs → `splunk-ao-a2a` (hyphenated; handled before the generic `galileo` rule to avoid producing the wrong underscore form)
- `Galileo.ai` brand name in prose → `Splunk AO`
- `Galileo` brand name in comments/docstrings → `Splunk AO`

### Doc files (`.md`, `.rst`)

Doc files are processed in three passes:

1. **URL pass**: known Galileo documentation URLs are rewritten to their Splunk AO equivalents:
- `https://docs.galileo.ai/` → `https://agent-observability-docs.splunk.com/`
- `.../add-galileo-to-crewai/add-galileo-to-crewai` → `.../add-splunk-ao-to-crewai/add-splunk-ao-to-crewai`
- `-galileo.md` filename references → `-splunk-ao.md`
- `-galileo.txt` filename references → `-splunk-ao.txt`
- `/what-is-galileo` → `/what-is-splunk-agent-observability`
- `/getting-started/logging` → `/concepts/logging/overview`
- `/concepts/experiments/overview` → `/sdk-api/experiments/experiments`
2. **Prose pass**: all the same symbol, import, env-var, and brand-name substitutions as Python files, with one exception — `logstream=` (no underscore) is **not** rewritten in docs to avoid corrupting env-var string values like `TRACELOOP_HEADERS="..., logstream=default, ..."`. `log_stream=` and `log_stream_name=` are still rewritten.
3. **Placeholder fix pass**: three corrections applied after the prose pass:
- `your-splunk_ao-*` → `your-splunk-ao-*` (hyphenated placeholder form)
- `splunk_ao-*` → `splunk-ao-*` (hyphenated package/dir names in prose, e.g. `splunk_ao-adk` → `splunk-ao-adk`)
- bare `splunk_ao` in prose position (not followed by `_`, `.`, `-`, or `/`) → `Splunk AO` (brand name)

All other URLs (`https?://...`) are **not rewritten** — external links remain intact.

### Dependency files

- `galileo` → `splunk-ao`
- `galileo-adk` → `splunk-ao-adk`
- `galileo-a2a` → `splunk-ao-a2a`
- `galileo_a2a` → `splunk_ao_a2a` (Python package identifier in paths and config)
- `galileo_adk` → `splunk_ao_adk`
- `sources = { galileo = ...}` → `sources = { "splunk-ao" = ...}` (uv TOML source key, quoted because hyphen is not valid in a bare TOML key)
- `GALILEO_*` env-var strings in `pyproject.toml` pytest `env = [...]` blocks → `SPLUNK_AO_*`
- `requires-python` floor below `3.11` → `>=3.11` (e.g. `>=3.10,<3.14` → `>=3.11,<3.14`)
- `Galileo` brand name in prose fields (e.g. `description`, `authors`) → `Splunk AO`

### Environment files

- All `GALILEO_*` keys → `SPLUNK_AO_*` (e.g. `GALILEO_API_KEY`, `GALILEO_API_ENDPOINT`, `GALILEO_CONSOLE_URL`, `GALILEO_PROJECT`, etc.)
- `GALILEO_LOGSTREAM` / `GALILEO_LOG_STREAM` → `SPLUNK_AO_AGENT_STREAM`
- HTTP header strings: `Galileo-API-Key` → `Splunk-AO-API-Key`, `X-Galileo-Trace-ID` → `Splunk-AO-Trace-ID`
- `galileo` as a word in placeholder values (e.g. `your-galileo-key` → `your-splunk-ao-key`)
- `galileo` inside underscore-delimited placeholder tokens (e.g. `your_galileo_api_key_here` → `your_splunk_ao_api_key_here`)
- `Galileo` brand name in comments → `Splunk AO`

### Filesystem paths

Directories and files are renamed after file content is rewritten, deepest-first
so child paths are handled before their parents:

- `galileo-a2a/` → `splunk-ao-a2a/`
- `galileo-adk/` → `splunk-ao-adk/`
- `galileo_a2a/` → `splunk_ao_a2a/` (Python package dirs use underscore)
- `galileo_` prefix in any directory or filename → `splunk_ao_`
- bare `galileo` directory name → `splunk_ao`

The root directory passed as the CLI argument is included in the rename scan,
so `splunk-ao-migrate galileo-a2a/` will rename the directory itself to `splunk-ao-a2a/`.

## Warnings (flagged, not auto-fixed)

- **Protect feature usage** (`invoke_protect`, `ainvoke_protect`, etc.) — keep `galileo`
as a dependency; Protect is not available in `splunk-ao`
- **`galileo_core` imports** — `galileo_core` is a low-level external dependency used
internally by `splunk-ao`. It is **not** renamed to `splunk_ao_core` (no such package
exists). When this warning fires, all `Metric`/`Evaluator` renames are suppressed for
the entire file (including call sites) so internal types like `Metrics` from
`galileo_core.schemas.logging.step` are not incorrectly renamed. Review the file to
confirm the suppressed renames are correct.
- **Dynamic env-var construction** (`f"GALILEO_{key}"`) — cannot be auto-rewritten;
update manually
- **Lowercase `galileo` in string literals** — may refer to the astronomer or other
non-SDK usage (e.g. `"what moons did galileo discover"`); verify whether it should
be renamed or left as-is

## Manual steps after migration

- **On-disk config directory**: the local config directory has moved from `~/.galileo/` to `~/.splunk/`.
Delete or migrate any `~/.galileo/galileo-python-config.json` to `~/.splunk/splunk-ao-config.json`
manually — the tool rewrites file content and names but does not touch directories outside the target path.

## Limitations

- Rules are applied to raw text, so occurrences in comments and docstrings are also
rewritten.
- URLs are not rewritten in Python, dependency, and environment files. In doc files
(`.md`, `.rst`), only the known Galileo documentation URLs listed above are rewritten;
all other external links are preserved as-is.
- **`galileo_core` interop code**: when a file imports from `galileo_core`, all
`Metric`/`Evaluator` renames (`Metrics`, `LlmMetric`, etc.) are suppressed for that
entire file — including call sites on lines that do not contain `galileo_core` —
because those names are `galileo_core` internals that must not be renamed. Other
identifiers in the same file (e.g. `_ADK_ROLE_TO_GALILEO`, `_map_adk_role_to_galileo`)
are still renamed. Review the output of files that trigger the `galileo_core` warning.

## See also

- `splunk-ao-migration-tool/README.md` — complete migration guide
30 changes: 30 additions & 0 deletions splunk-ao-migration-tool/splunk_ao_migrate/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
[project]
name = "splunk-ao-migrate"
version = "0.1.0"
description = "Regex-based CLI to migrate Python code from the galileo SDK to splunk-ao-python"
readme = "README.md"
requires-python = ">=3.11"
license = { text = "Apache-2.0" }
keywords = ["migration", "galileo", "splunk-ao", "codemod"]
dependencies = [] # stdlib only — no external dependencies

[project.scripts]
splunk-ao-migrate = "splunk_ao_migrate.migrate:main"

[project.urls]
Repository = "https://github.com/splunk/splunk-ao-python"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/splunk_ao_migrate"]

[dependency-groups]
dev = [
"pytest>=8.0",
]

[tool.pytest.ini_options]
testpaths = ["tests"]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# splunk_ao_migrate — automated galileo → splunk-ao migration tool
Loading
Loading