feat: add unified storage interface - #3099
Conversation
cf9da16 to
7aac8bc
Compare
|
Assessment: Request Changes Clean, well-documented storage primitive with strong unit coverage — but the adapters that wire it into existing subsystems have a correctness gap and some contract mismatches worth resolving before merge. Review themes
The backwards-compat approach (duck-typed detection, deprecation aliases, |
|
Issue (Important): This PR introduces a substantial new public surface — the Suggestion: Add |
Review SummaryAssessment: Request Changes Well-structured PR with a clean primitive, good normalization/path-traversal guards, and thorough tests for the storage implementations themselves. The main concern is that the adapter bridging the new Review Categories
The overall shape of the abstraction is solid — resolving the content-type round trip is the key thing before this is ready. |
|
Re-review of Assessment: Comment (downgraded from my prior Approve, pending one API-shape decision)
Details
Everything else from prior passes remains resolved — this is down to a single API decision. |
Remove outdated evictAfterTurns doc, update snapshot-storage-adapter to reference .namespace() method, simplify namespace() return type now that the method is on the Storage interface.
|
Re-review of Assessment: Comment This tidies docstrings and simplifies the factory return type to plain Details
Everything else remains resolved — this is down to the single interface-declaration decision. |
|
Re-review of tip The only change since So all prior feedback still stands. The one remaining substantive item is unchanged: the Assessment: Comment — no re-review needed for the merge itself; the open API decision (make |
Constructs like SessionManager auto-namespace with a default prefix (e.g. 'session') only when the user hasn't already scoped the storage. The NAMESPACED symbol on views returned by namespace() enables this detection without adding to the public Storage interface.
|
Re-review of Assessment: Comment Nice approach — the Three items remain (details inline): Open items
The core mechanism is solid; this is mostly about test coverage for the new branch and a consistency decision across constructs. |
|
Thanks for the latest change, this enables migration! I would suggest to clearly document this in the docstrings of Reviewer bot called out a few gaps, but I'm fine to do that as follow-up |
|
will update tests and doc strings in python/docs port |
|
@strandly-the-agent port this to a python implementation |
Summary
Adds the unified
Storage<ListQuery>interface — the single persistence primitive for the SDK — and wires it into existing subsystems (context offloader, session manager).API
Four operations over opaque
Uint8Arrayvalues. Keys are/-separated path-like strings. The genericListQuerydefaults to string (prefix match) but can be widened by backends like DynamoDB.Shipped implementations:
InMemoryStorageMap@strands-agents/sdk/storageLocalFileStorage@strands-agents/sdk/storageS3Storage@strands-agents/sdk/storageDeveloper Experience
Changes
Storage primitive (
src/storage/storage.ts):Storage<ListQuery = string>interface withwrite,read,delete,listnamespace()helper for key-prefix scoping (composable)//, strips leading/trailing/, rejects..segmentsStorageErrorinsrc/errors.ts;./storagesubpath exportImplementations:
InMemoryStorage: Map-backed, for testing and serverlessLocalFileStorage: atomic writes (tmp + rename), recursive directory walking, sandbox-aware viaforSandbox()S3Storage: lazy@aws-sdk/client-s3import, paginated listing, prefix namespacingContext offloader adaptation:
Storageor legacyOffloaderStorage(duck-type detection)agent.metrics.cycleCount, deletes entries older thanevictAfterCycles(default 20,nulldisables)evictAfterCyclesalso flows to legacy storage when the user hasn't explicitly setevictAfterTurnsSession manager adaptation:
SnapshotStorageAdapterbridges unifiedStorage→SnapshotStorageSessionManagerConfig.storageacceptsStoragedirectly (or legacy{ snapshot: SnapshotStorage })Future Work
Phase 1 of the unified storage design. Planned next:
LocalMemoryStoreaccepts optionalStorage)Storage)Testing
Checklist