Repository navigation
Conversation
Updated regex pattern in getReference function and adjusted file path checks in tests.
|
@strandly-the-agent review that this ports the python feature correctly. And do a general review aswell |
strandly-the-agent
left a comment
There was a problem hiding this comment.
Port is faithful except one gap: host-mode retrieve still rejects legacy relative path references (the default ./artifacts config), which Python accepts. Approving — the divergence is non-blocking, but the PR body claims legacy paths keep working, and for the default config they don't. Two inline 🟡s (that gap, plus a small host-mode regression for keys ending in .), both with validated one-line fixes.
What matches Python (storage.py:174-309, #4568): bare-filename return in host and sandbox mode, legacy-path acceptance in sandbox mode (exact <artifactDir>/ shape the old TS emitted), stem lookup via .metadata.json (unique match only, ambiguous → not found), fallback to the raw name when metadata is missing, .. and out-of-dir rejection, Reference not found on miss. Verified by probe, not just read.
✅ Verified
- Head
a53479c1b, basemain(b7900ae68). cd strands-ts && npx vitest run --project unit-node src/vended-plugins/context-offloader→ 6 files, 132/132 pass, no type errors.- Probe on head (host mode,
new FileStorage('./artifacts'), cwd = tmpdir): bare ✅, stem ✅, absolute legacy path ✅,./artifacts/<f>❌ Reference not found,artifacts/<f>❌, ambiguous stem → not found ✅,''/./../…/a/sub/../f/ symlinked dir //etc/hostnameall rejected ✅. - Same probe with the two suggested fixes applied: legacy relative refs and
k..txtround-trip, traversal still rejected, 132/132 still pass. - On
main, host mode with a relative dir was already broken even for the fresh round trip (storereturnedartifacts/<f>,retrievenested it). This PR fixes that forward; the inline comment is about refs that predate it. - Adversarial pass held: sandbox legacy forms across
./artifacts,artifacts,artifacts/, absolute, backslash dirs; backslash/NUL/trailing-slash refs; stem collisions; odd content types; unicode keys; parallelstore()on a loaded instance. Plugin surface (plugin.ts:340-347, 419-441) never tells the model a reference is a path, so the bare filename fits.
Port-fidelity table
| Behaviour | Python storage.py |
TS PR storage.ts |
|
|---|---|---|---|
store returns bare filename (host / sandbox) |
:245 / :234 | :321 / :302 | ✅ |
| Legacy full path, sandbox | parent resolves to dir :191-195 | exact prefix strip :330-332 — matches every ref old TS sandbox store produced |
✅ |
| Legacy full path, host, absolute dir | ✅ | ✅ | ✅ |
| Legacy full path, host, relative dir (default) | ✅ Path(ref).parent.resolve() |
❌ path.resolve(artifactDir, ref) nests it :349 |
🟡 inline |
| Stem → filename via metadata, unique only | :200-207 | _knownFilename :281-287 |
✅ |
| Metadata missing → raw name fallback | _resolve_from_path |
_knownFilename returns candidate |
✅ |
.. rejection |
substring :189 | substring :331, :350 | ✅ same — and same over-match, see inline |
| Out-of-dir rejection | :194, :306 | :332, :350 | ✅ |
| Error | KeyError('Reference not found: …') |
Error('Reference not found: …') |
✅ |
Reading order
storage.ts:281-287_knownFilename.storage.ts:326-343sandboxretrieve,:345-363hostretrieve.__tests__/storage.test.node.ts:48-64— note both legacy-path tests use an absolutetmpDironly.
Appendix — non-blocking (5)
- ⚪ Test gaps: legacy path with the default relative dir (would have caught the inline 🟡); ambiguous stem (probe confirms it rejects; a test would pin it).
storage.test.node.ts:44expect(ref).not.toContain(tmpDir)passes for any relative path — the sandbox file'snot.toContain('/')is the stronger assertion. - ⚪
storage.ts:284filename.slice(0, filename.lastIndexOf('.'))drops the last char when a metadata key has no dot (lastIndexOf= -1). Only reachable with hand-edited metadata sincestorealways appends an extension. - ⚪
storage.ts:282Object.hasOwn(this._contentTypes, …)runs outside thetry; a.metadata.jsoncontainingnullnow throwsTypeErrorinstead ofReference not found. Guard in_loadMetadata/_loadSandboxMetadata(return{}unless plain object). - ⚪
storage.ts:329addsthis._artifactDir.replace(/\/+$/, ''), the patternstripTrailingSlashes(:56) exists to avoid;:226already does the same, so consistency either way. - ⚪ Pre-existing, not filed (deprecated class — say if you want an issue):
_ensureSandbox(:244-247) sets_metadataLoadedafter theawait, so the first parallelstore()calls on a fresh instance each load metadata and the later assignment clobbers the earlier entry. Reachable via the plugin'sPromise.allatplugin.ts:476on an agent's first multi-block offload → wrong content type / stem lookup miss for the clobbered block. Also pre-existing:.metadata.jsonis itself retrievable as a reference (both languages); host mode follows symlinks inside the dir (Python's.resolve()+is_relative_todoesn't).
|
Thanks for the catch. Both are fixed and pushed: host-mode retrieval now resolves older relative refs against the working directory (4a10cd6), and the |
|
@charan-rathore Hi, thanks for the contribution. I left a few comments on this PR. |
store() can return a filename containing ".." (e.g. a key ending in a dot produces "<ts>_<n>_Summary..txt"), which sandbox retrieve then rejected via a substring check. Reject only the exact "." and ".." references instead, mirroring the host-mode segment check, and document both guards. Co-authored-by: liramon2 <[email protected]> Signed-off-by: Charan Rathore <[email protected]>
|
@liramon2 thanks for the careful read. Both nits (storage.ts:331 and :351) are fixed, and the ".." check had a real bug: store() can return a filename containing ".." (a key ending in a dot produces |
…trands-agents#4668) Signed-off-by: Charan Rathore <[email protected]> Co-authored-by: liramon2 <[email protected]>
Description
Legacy TypeScript FileStorage returned the machine's artifact path as an offload reference. That path would stop working when the stored reference moved with a conversation. Both local and sandbox storage now return only the filename. Retrieval still accepts older paths within the configured artifact directory and bare stems found in metadata. Host-mode retrieval also handles older relative paths when the artifact directory is configured relatively, and allows a filename containing
..without permitting a..path segment. Unknown stems and paths outside that directory remain rejected.Related Issues
Fixes #4665
Follow-up to #4568, which fixed the Python backend; this applies the same fix to the TypeScript backend, where the bug is still present on current main.
Documentation PR
No site documentation change is needed for this legacy backend; its code documentation now describes the filename reference.
Type of Change
Bug fix
Testing
Instinct assisted with the change and tests.