Commit 3fe739f
committed
fix(harness): stop orphan GC from deleting skills other calls still use
Fixes #2787
MarketplaceStager rebuilt its retain-list from a single call's visible
skills and then deleted every other directory under a `.skills-cache` tree
shared by every call against the workspace. With per-user skill visibility,
call B's "orphan" was call A's live filesRoot, so B removed a directory A
had just staged - often while A was still walking it, which surfaced as an
UncheckedIOException out of onSystemPrompt that failed the whole agent call
before its first model round.
Two changes, matching the two defects in the issue.
Traversal no longer aborts on a vanished entry. deleteRecursively uses
Files.walkFileTree, so an entry removed mid-walk is reported through
visitFileFailed instead of ending the traversal; removeUnexpected and
garbageCollectOrphans also catch UncheckedIOException, which Files.walk and
Files.list throw for mid-iteration IO errors and which is not an IOException;
and the GC call is wrapped so cache hygiene can never fail an agent call,
mirroring the fallback already applied per skill.
Staging is scoped, following the issue's own suggestion to prefix
`.skills-cache` with the namespace IsolationScope already applies to runtime
data. Skills now materialise under `.skills-cache/<scope>/<source-ns>/<name>/`,
where the scope is the call's userId (or sessionId, matching
IsolationScope.USER's documented fallback). Calls that do not share a scope
cannot address each other's subtree, so a white-list built from one call's
visible skills is authoritative for everything its sweep can reach - the
property the flat layout never had. A short grace window remains as a backstop
for entries whose visibility changes within a scope.
The scope must be at least as fine as the visibility dimension. The default,
USER, matches the per-user visibility filters this failure was reported
against; an agent that combines AGENT or GLOBAL scope with per-user visibility
still shares one subtree and relies on the grace window alone.
Tests:
- MarketplaceStagerOrphanGcTest keeps a fresh orphan, still reclaims a stale
one, survives concurrent callers with differing visible sets, degrades
rather than throwing on an unreadable entry, and asserts that an aged
directory in one scope is unreachable by another scope's sweep.
- SharedWorkspaceSkillStagingE2ETest drives the real middleware path: two
agents sharing one workspace, per-user visibility asserting that no prompt
ever advertises a files-root missing from disk, and a deterministic case
where one user's call must not delete another user's staged skill.
Each of those fails against the unpatched stager. Full suite: 89/89 modules,
5983 tests, 0 failures.1 parent 4ba433a commit 3fe739f
8 files changed
Lines changed: 885 additions & 38 deletions
File tree
- agentscope-harness/src
- main/java/io/agentscope/harness/agent
- middleware
- skill/runtime
- test/java/io/agentscope/harness/agent
- middleware
- skill/runtime
Lines changed: 1 addition & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2775 | 2775 | | |
2776 | 2776 | | |
2777 | 2777 | | |
| 2778 | + | |
2778 | 2779 | | |
2779 | 2780 | | |
2780 | 2781 | | |
| |||
Lines changed: 43 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| 24 | + | |
24 | 25 | | |
25 | 26 | | |
26 | 27 | | |
| |||
81 | 82 | | |
82 | 83 | | |
83 | 84 | | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
84 | 113 | | |
85 | 114 | | |
86 | 115 | | |
| |||
169 | 198 | | |
170 | 199 | | |
171 | 200 | | |
| 201 | + | |
172 | 202 | | |
173 | 203 | | |
174 | 204 | | |
| |||
186 | 216 | | |
187 | 217 | | |
188 | 218 | | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
189 | 228 | | |
190 | 229 | | |
191 | 230 | | |
| |||
213 | 252 | | |
214 | 253 | | |
215 | 254 | | |
216 | | - | |
| 255 | + | |
217 | 256 | | |
218 | 257 | | |
219 | 258 | | |
| |||
239 | 278 | | |
240 | 279 | | |
241 | 280 | | |
242 | | - | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
243 | 284 | | |
244 | 285 | | |
245 | 286 | | |
| |||
0 commit comments