Skip to content

Commit 6d1ca97

Browse files
mjnoviceclaude
andauthored
feat: scaffold MemoryService for Agent Episodic Memory (URT migration) (#1467)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent b8dba25 commit 6d1ca97

10 files changed

Lines changed: 1425 additions & 5 deletions

File tree

.github/workflows/test-packages.yml

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,55 @@ jobs:
130130
working-directory: packages/uipath-platform
131131
run: uv run pytest
132132

133+
e2e-uipath-platform:
134+
name: E2E (uipath-platform, memory)
135+
needs: detect-changed-packages
136+
runs-on: ubuntu-latest
137+
steps:
138+
- name: Check if package changed
139+
id: check
140+
shell: bash
141+
run: |
142+
if echo '${{ needs.detect-changed-packages.outputs.packages }}' | jq -e 'index("uipath-platform")' > /dev/null; then
143+
echo "skip=false" >> $GITHUB_OUTPUT
144+
else
145+
echo "skip=true" >> $GITHUB_OUTPUT
146+
fi
147+
148+
- name: Skip
149+
if: steps.check.outputs.skip == 'true'
150+
shell: bash
151+
run: echo "Skipping - no changes to uipath-platform"
152+
153+
- name: Checkout
154+
if: steps.check.outputs.skip != 'true'
155+
uses: actions/checkout@v4
156+
157+
- name: Setup uv
158+
if: steps.check.outputs.skip != 'true'
159+
uses: astral-sh/setup-uv@v5
160+
161+
- name: Setup Python
162+
if: steps.check.outputs.skip != 'true'
163+
uses: actions/setup-python@v5
164+
with:
165+
python-version: "3.11"
166+
167+
- name: Install dependencies
168+
if: steps.check.outputs.skip != 'true'
169+
working-directory: packages/uipath-platform
170+
run: uv sync --all-extras --python 3.11
171+
172+
- name: Run E2E memory tests
173+
if: steps.check.outputs.skip != 'true'
174+
working-directory: packages/uipath-platform
175+
env:
176+
UIPATH_URL: ${{ secrets.ALPHA_BASE_URL }}
177+
UIPATH_CLIENT_ID: ${{ secrets.ALPHA_TEST_CLIENT_ID }}
178+
UIPATH_CLIENT_SECRET: ${{ secrets.ALPHA_TEST_CLIENT_SECRET }}
179+
UIPATH_FOLDER_KEY: ${{ secrets.UIPATH_MEMORY_FOLDER }}
180+
run: uv run pytest tests/services/test_memory_service_e2e.py -m e2e -v --no-cov
181+
133182
test-uipath:
134183
name: Test (uipath, ${{ matrix.python-version }}, ${{ matrix.os }})
135184
needs: detect-changed-packages
@@ -184,7 +233,7 @@ jobs:
184233

185234
test-gate:
186235
name: Test
187-
needs: [test-uipath-core, test-uipath-platform, test-uipath]
236+
needs: [test-uipath-core, test-uipath-platform, test-uipath, e2e-uipath-platform]
188237
runs-on: ubuntu-latest
189238
if: always()
190239
steps:
@@ -196,4 +245,8 @@ jobs:
196245
echo "Tests failed"
197246
exit 1
198247
fi
248+
# E2E tests are informational — log but don't block
249+
if [[ "${{ needs.e2e-uipath-platform.result }}" == "failure" ]]; then
250+
echo "⚠️ E2E memory tests failed (non-blocking)"
251+
fi
199252
echo "All tests passed"

packages/uipath-platform/pyproject.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "uipath-platform"
3-
version = "0.1.30"
3+
version = "0.1.31"
44
description = "HTTP client library for programmatic access to UiPath Platform"
55
readme = { file = "README.md", content-type = "text/markdown" }
66
requires-python = ">=3.11"
@@ -98,9 +98,12 @@ warn_required_dynamic_aliases = true
9898
[tool.pytest.ini_options]
9999
testpaths = ["tests"]
100100
python_files = "test_*.py"
101-
addopts = "-ra -q --cov=src/uipath --cov-report=term-missing"
101+
addopts = "-ra -q --cov=src/uipath --cov-report=term-missing -m 'not e2e'"
102102
asyncio_default_fixture_loop_scope = "function"
103103
asyncio_mode = "auto"
104+
markers = [
105+
"e2e: end-to-end tests against real ECS/LLMOps (requires UIPATH_URL, UIPATH_ACCESS_TOKEN, UIPATH_FOLDER_KEY)",
106+
]
104107

105108
[tool.coverage.report]
106109
show_missing = true

packages/uipath-platform/src/uipath/platform/_uipath.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from .entities import EntitiesService
2323
from .errors import BaseUrlMissingError, SecretMissingError
2424
from .guardrails import GuardrailsService
25+
from .memory import MemoryService
2526
from .orchestrator import (
2627
AssetsService,
2728
AttachmentsService,
@@ -113,6 +114,10 @@ def context_grounding(self) -> ContextGroundingService:
113114
self.buckets,
114115
)
115116

117+
@property
118+
def memory(self) -> MemoryService:
119+
return MemoryService(self._config, self._execution_context, self.folders)
120+
116121
@property
117122
def documents(self) -> DocumentsService:
118123
return DocumentsService(self._config, self._execution_context)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""Init file for memory module."""
2+
3+
from ._memory_service import MemoryService
4+
from .memory import (
5+
CachedRecall,
6+
EscalationMemoryIngestRequest,
7+
EscalationMemoryMatch,
8+
EscalationMemorySearchResponse,
9+
FieldSettings,
10+
MemoryMatch,
11+
MemoryMatchField,
12+
MemorySearchRequest,
13+
MemorySearchResponse,
14+
MemorySpace,
15+
MemorySpaceCreateRequest,
16+
MemorySpaceListResponse,
17+
SearchField,
18+
SearchMode,
19+
SearchSettings,
20+
)
21+
22+
__all__ = [
23+
"CachedRecall",
24+
"EscalationMemoryIngestRequest",
25+
"EscalationMemoryMatch",
26+
"EscalationMemorySearchResponse",
27+
"FieldSettings",
28+
"MemoryMatch",
29+
"MemoryMatchField",
30+
"MemorySearchRequest",
31+
"MemorySearchResponse",
32+
"MemoryService",
33+
"MemorySpace",
34+
"MemorySpaceCreateRequest",
35+
"MemorySpaceListResponse",
36+
"SearchField",
37+
"SearchMode",
38+
"SearchSettings",
39+
]

0 commit comments

Comments
 (0)