Skip to content

feat(DATAGO-131493): User can run the experiment and view the result#1473

Merged
ziyanwan merged 2 commits intomainfrom
feat/eval-activity-diagrams-support
Apr 29, 2026
Merged

feat(DATAGO-131493): User can run the experiment and view the result#1473
ziyanwan merged 2 commits intomainfrom
feat/eval-activity-diagrams-support

Conversation

@josephabonasara
Copy link
Copy Markdown
Contributor

What is the purpose of this change?

Unblocks the enterprise eval pipeline's per-example activity diagram by exposing two reusable primitives from community SAM:

  1. A pure utility for the live-SSE-stream → visualizer mapping (so the enterprise eval pipeline can persist events in the same shape chat streams).
  2. A local-filesystem object-storage backend (so eval storage works in dev environments with no S3 infra).

Without these two additions, enterprise either has to fork/duplicate community mapping logic or require every developer to spin up MinIO before they can use eval features that rely on persisted artifacts.

How was this change implemented?

Public visualization mapper utility

  • New src/solace_agent_mesh/gateway/http_sse/visualization_mapper.py exporting the pure function infer_visualization_event_details(topic, payload, log_identifier=""). Body lifted verbatim from WebUIBackendComponent._infer_visualization_event_details; the only change is self.log_identifier becomes a parameter.
  • src/solace_agent_mesh/gateway/http_sse/component.py — the existing method becomes a one-line delegating wrapper. Zero behavior change for chat.
  • The enterprise eval pipeline calls this utility at upload time so the persisted event shape matches what chat streams live, eliminating the risk of a frontend mapping shim drifting from the backend mapper.

Filesystem object-storage backend

  • New src/solace_agent_mesh/services/platform/storage/filesystem_client.pyFileSystemStorageClient implementing ObjectStorageClient against a local directory. One file per object ({root}/{bucket}/{key}). get_public_url / generate_presigned_url return file:// URIs.
  • src/solace_agent_mesh/services/platform/storage/factory.py — adds "filesystem" / "fs" / "local" aliases. Default is still "s3"; existing callers are unaffected.

Key Design Decisions

  • Why extract the mapper as a pure function rather than persist {topic, payload} and rebuild on the frontend. Keeping mapping logic in one place (Python) avoids drift between a backend implementation and a TS port. The persisted shape matches what chat already produces, so the visualizer code path is shared between live and replay.
  • Why a separate filesystem backend rather than an in-memory mock for dev. The existing EvalStorageService round-trips bytes through the ObjectStorageClient interface; a filesystem implementation is the lowest-friction way to make the dev experience match production semantics without requiring MinIO. Real disk also makes failure-mode testing (size limits, permissions, prefix delete) realistic.
  • Why a separate test module for filesystem storage. The existing tests/unit/shared/storage/test_object_storage.py imports azure.storage.blob at module top, so it requires the optional Azure SDK to even collect. Filesystem tests live in their own module so they run in any minimal env.

How was this change tested?

  • Unit tests: tests/unit/gateway/http_sse/test_visualization_mapper.py — 7 tests pinning the standalone function's contract (system events, topic-fallback for request/response/status, payload-summary truncation, serialization-failure handling).
  • Unit tests: tests/unit/shared/storage/test_filesystem_storage.py — 11 tests exercising the real disk path: round-trip put/get, factory aliases (filesystem/fs/local/FILESYSTEM), delete-prefix subtree behavior, missing-key StorageNotFoundError, list_objects, and file:// public URLs.
  • Manual testing: ran an end-to-end eval experiment in enterprise with the filesystem backend (~/.sam-data/object-storage/sam-eval-data/...); confirmed the per-example activity diagram renders the same flow chart the chat panel produces for the same agent.
  • Regression: chat behavior is untouched. The component method now delegates to the extracted utility; existing tests for WebUIBackendComponent continue to pass.
  • Integration tests: none added — both new pieces are pure-function / pure-IO units already covered comprehensively at the unit level.

Is there anything the reviewers should focus on/be aware of?

  • component.py diff is a behavior-preserving extraction. The 178-line removal is the original mapper body; the addition is a one-line return infer_visualization_event_details(topic, payload, self.log_identifier). Worth a quick eyeball to confirm no logic was dropped.
  • FileSystemStorageClient.delete_prefix has three code paths (target is dir / file / key-prefix string match). The third branch covers the case where the prefix doesn't correspond to a real directory but is a true key-substring — matches the behavior real S3 clients implement. All three are exercised by the new tests.
  • generate_presigned_url silently ignores expires_in. Filesystem can't honor expiry; this is documented as a dev-only backend.
  • put_object metadata is accepted and silently dropped (S3/Azure persist it). Acceptable for a dev backend; flagged here in case reviewers want a sidecar metadata file added before merge.

Two strict additions enable the enterprise eval pipeline to persist the
captured A2A event stream alongside its existing execution-data blob and
to run end-to-end in local-dev environments without S3.

1. Public visualization mapper utility
   - New `gateway/http_sse/visualization_mapper.py` exporting the pure
     function `infer_visualization_event_details(topic, payload, log_identifier="")`,
     lifted from `WebUIBackendComponent._infer_visualization_event_details`.
   - The component method now delegates to this utility — zero behavior
     change for chat. The eval pipeline (in enterprise) calls the same
     utility at upload time so the persisted event shape matches what
     chat streams live; no separate frontend mapping path.

2. Filesystem object-storage backend
   - New `services/platform/storage/filesystem_client.py` —
     `FileSystemStorageClient` implementing `ObjectStorageClient` against
     a local directory (one file per object, file:// URLs).
   - `factory.py` accepts `"filesystem"` / `"fs"` / `"local"` aliases.
     Default remains `"s3"`; existing callers are unaffected.
   - Lets enterprise initialize its eval storage service with no S3 infra
     when `EVAL_DATA_BUCKET_NAME` is unset, so activity diagrams and
     execution-data views work in a developer's local SAM out of the box.

Tests:
   - `tests/unit/gateway/http_sse/test_visualization_mapper.py` — 7 tests
     pinning the contract of the standalone function (system events,
     topic-fallback for request/response/status, payload-summary
     truncation, serialization-failure handling).
   - `tests/unit/shared/storage/test_filesystem_storage.py` — 11 tests
     covering the real disk path: round-trip put/get, factory aliases,
     delete-prefix subtree behavior, missing-key 404, list_objects, and
     file:// URLs. Lives in its own module because the existing
     `test_object_storage.py` imports the optional Azure SDK at module top.
@josephabonasara josephabonasara requested a review from Copilot April 28, 2026 19:10
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 28, 2026

✅ FOSSA Guard: Licensing (SolaceLabs_solace-agent-mesh) • PASSED

Compared against main (b75ead325e409a3def350b4688fabd52fff247de) • 0 new, 9 total (9 in base)

Scan Report | View Details in FOSSA

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 28, 2026

✅ FOSSA Guard: Vulnerability (SolaceLabs_solace-agent-mesh) • PASSED

Compared against main (b75ead325e409a3def350b4688fabd52fff247de) • 0 new, 8 total (8 in base)

Scan Report | View Details in FOSSA

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extracts the SSE visualization event “details” mapper into a reusable pure function and introduces a local filesystem-backed ObjectStorageClient to unblock dev/eval workflows without requiring S3/MinIO.

Changes:

  • Added infer_visualization_event_details(topic, payload, log_identifier="") as a standalone utility and updated the Web UI component to delegate to it.
  • Added FileSystemStorageClient plus factory support for filesystem/fs/local backends.
  • Added focused unit tests for the mapper utility and filesystem storage backend.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/solace_agent_mesh/gateway/http_sse/visualization_mapper.py New pure visualization mapping utility extracted from the component.
src/solace_agent_mesh/gateway/http_sse/component.py Delegates visualization mapping to the new utility to keep behavior consistent.
src/solace_agent_mesh/services/platform/storage/filesystem_client.py New filesystem-backed object storage client implementation.
src/solace_agent_mesh/services/platform/storage/factory.py Adds filesystem backend aliases and wiring via env var root.
tests/unit/gateway/http_sse/test_visualization_mapper.py Unit tests pinning the mapper utility’s contract.
tests/unit/shared/storage/test_filesystem_storage.py Unit tests for filesystem storage behavior and factory aliases.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/solace_agent_mesh/services/platform/storage/filesystem_client.py Outdated
Comment thread src/solace_agent_mesh/services/platform/storage/filesystem_client.py Outdated
@josephabonasara josephabonasara self-assigned this Apr 28, 2026
@josephabonasara josephabonasara changed the title Feat(DATAGO-131493): User can run the experiment and view the result feat(DATAGO-131493): User can run the experiment and view the result Apr 28, 2026
@josephabonasara josephabonasara requested review from bwiebe-solace and removed request for bwiebe-solace April 28, 2026 19:16
Address review feedback on the dev/test filesystem backend:

- Resolve _root to an absolute path in __init__ so as_uri() (used by
  generate_presigned_url / get_public_url) works when callers pass a
  relative root_path.
- Reject empty keys, absolute keys, and any key that resolves outside
  the bucket root in _path_for. Defense-in-depth — current callers
  pass server-constructed keys, but the class is part of the public
  storage interface.
- Use Path.as_posix() in list_objects and the delete_prefix string-
  match fallback so returned/compared keys use '/' on every platform,
  matching the convention of the cloud backends.

Tests:
- TestRelativeRootPath verifies a relative root produces a usable
  file:// URL.
- TestPathTraversalRejected covers ../, /etc/passwd, mid-key escape,
  empty key, and a "doesn't leak through get_object" case.
- TestListAndUrls extended with an explicit POSIX-separator assertion.

Skipped sidecar persistence of content_type/metadata: no current
caller reads those fields from this backend; can be added if a real
use case appears.
@sonarqube-solacecloud
Copy link
Copy Markdown

Quality Gate failed Quality Gate failed

Failed conditions
57.3% Coverage on New Code (required ≥ 60%)

See analysis details on SonarQube

Copy link
Copy Markdown
Contributor

@bwiebe-solace bwiebe-solace left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@ziyanwan ziyanwan merged commit a42a3f5 into main Apr 29, 2026
26 of 31 checks passed
@ziyanwan ziyanwan deleted the feat/eval-activity-diagrams-support branch April 29, 2026 13:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants