mirror of
https://github.com/desplega-ai/agent-fs.git
synced 2026-09-14 20:46:59 +08:00
bedd7b7953
* [Phase 1] Daemon-start fix + Optional FUSE subpackage fix
- daemon.ts: respawn via process.argv[1] so npm-installed CLI starts cleanly
(was: dist/index.ts ENOENT under the isCompiled heuristic).
- fuse-helper-linux-{x64,arm64}: drop libc array; os+cpu is the correct
constraint and matches esbuild/swc/rollup convention. Fixes npm silently
skipping the optional FUSE subpackage on first global install.
- cli/package.json: relax exact 0.6.1 pins to ^0.7.0 (npm/cli#4828 family).
- sync-versions.ts: preserve carets on @desplega.ai/agent-fs-fuse-* pins.
- daemon-respawn.test.ts: regression test for the npm-install layout.
* [Phase 2] CLI plumbing — mount --remote flag + helper arg passing
- mount.ts: new --remote / --api-url / --api-key flags. Skips local daemon
socket check when remote; forwards API key via child env only, never argv.
Implicit remote opt-in when --api-url/--api-key supplied without --remote.
- fuse-args.ts: pure buildHelperSpawnArgs() composing argv + env for
local vs remote modes; enforces mutual exclusion invariants.
- remote-config.ts: resolveRemoteCreds() with flags > env > config
precedence; tolerant of auth.apiKey fallback + malformed config.
- 21 unit tests (12 for fuse-args, 9 for remote-config).
Helper still rejects --api-url — intentional, Phase 3 lands HTTP transport.
* [Phase 3] HttpIpcClient — read-only ops + new CLI args
- Cargo.toml: reqwest 0.12 (rustls-tls/json/stream — no native-tls for
musl-static compat), bytes, once_cell, wiremock dev-dep, clap `env`.
- main.rs: --api-url / --api-key clap args (env-backed, hide_env_values
on key). Transport selection branches on both-present.
- ipc.rs: HttpIpcClient for Ping/Hello/ListDrives/DefaultDriveSlug/
GetAttr/ReadDir/OpenRead. Mutating ops return synthetic EROFS until
Phase 4 (safer than unreachable!()). Shared with_retry helper between
Unix + HTTP clients. Drive-table + auth/me caches. get_attr dir-probe
fallback via ls mirrors daemon handlers.ts behavior.
- fs.rs: relax I to ?Sized; add FuserAdapter::from_arc for the unsized
dyn IpcTrait path. Existing Sized constructor preserved for tests.
- tests/http_ipc_roundtrip.rs: 10 wiremock-driven integration tests.
- Dockerfile.test: bump pinned toolchain 1.85.0→1.86.0 (reqwest →
icu_* MSRV).
54 Rust tests pass. Release binary size 2.5 MB (1.7× baseline).
* [Phase 4] HttpIpcClient — write ops + conflict handling
- ipc.rs: real HTTP impls replace Phase 3 EROFS stubs for OpenWrite,
CreateFile, Truncate, Unlink, Rename, Mkdir, Rmdir. Added
parse_version_headers (ETag → version, X-Agent-Fs-Content-Hash) and
decode_http_error helpers.
- 409 EDIT_CONFLICT propagates through Response::Error → kernel sees
EIO via the existing errno mapping.
- Rename across drives short-circuits to EXDEV without an HTTP call.
- Truncate reuses do_open_read + do_open_write for the RMW path so URL
encoding + header parsing stay in one place.
- Mkdir is a true local no-op matching daemon behaviour.
- 11 new wiremock tests covering write happy / conflict / EXDEV / mkdir
/ rmdir / truncate paths. 64 total tests green.
Docker --http harness deferred to Phase 5.
* [Phase 5] E2E coverage for remote mount
- scripts/e2e-remote-mount.ts: Docker-based harness. Daemon on host,
helper in container, talking over host.docker.internal. 9 ops:
mount, ls drives + current symlink, mkdir, host→mount visibility,
echo+cat roundtrip, ls reflects new file, mv within drive, rm,
fusermount3 -u. ~4 min wallclock end-to-end with cargo build.
- Dockerfile.e2e-fuse: bump rustc 1.85→1.86 (matches Phase 3's
Dockerfile.test bump — reqwest → icu_* MSRV). Benefits the existing
e2e.ts FUSE suite too.
- README.md: link to the harness from the FUSE mount section.
- bun.lock: catch up to 0.6.1 + ^0.7.0 caret pins already on disk.
* [Phase 6] docs/mounting — general + sprite + e2b + hetzner
- docs/mounting/README.md: ASCII two-topology diagram (local daemon vs
--remote), prereqs table, auth model, top-4 troubleshooting cribbed
from the 2026-05-18 sprite test, per-env doc table.
- docs/mounting/sprite.md: the 4 prereq commands + idempotent one-liner
bash script for re-running on fresh sprites.
- docs/mounting/e2b.md: marked Status: untested; documents expected
Dockerfile + mount flow + risk checklist + CLI fallback. Existing
fuse-compat.md confirms E2B kernel has CONFIG_FUSE_FS=y; remaining
unknowns flagged for reader reports.
- docs/mounting/hetzner.md: 4-step happy path + systemd unit example.
- README.md: link to docs/mounting/README.md under FUSE section;
consolidated with Phase 5's --remote subsection without duplication.
* [Phase 7] v0.7.0: FUSE remote-mount + daemon-start + optional-dep fixes
- Version bump to 0.7.0 across all packages, plugin, Cargo, openapi.
- skills/agent-fs/SKILL.md: mount/fuse/remote/sandbox triggers added;
Remote mode section + --remote command-table row; sprite prereqs
example in workflow examples.
- Release notes filed under thoughts/taras/learnings/ (notes/ dir is
blocked by validate-thoughts.py hook).
- Plan checkboxes updated for pre-release verification; post-tag-push
boxes left unchecked until release.sh runs.
Pre-release verification all green:
- typecheck, 324 unit tests, e2e (68/68), e2e-remote-mount (9/9)
- cargo test (64), clippy --all-targets -D warnings, fmt --check
* qa: v0.7.0 Hetzner + sprite end-to-end passed
- Hetzner VM (cx23, Ubuntu 24.04): B-1..B-7 all PASS. agent-fs 0.7.0
installed via npm (Node 22 + Bun), daemon-start bug fixed, mount
--remote against fly works, write/mv/rm roundtrip clean.
- Sprite (code-health-scan, Ubuntu 25.10): C-1..C-6 all PASS. All 4
FUSE prereqs already in place. bun install -g, native cargo build
(1m6s), mount --remote against fly works end-to-end.
Findings (not blocking 0.7.0, follow-ups):
- F-1: npm install -g aborts on Ubuntu 24.04 default Node 18.19.1 due
to node-llama-cpp postinstall syntax error. Workaround: Node 20+ or
bun install -g (which the Hetzner doc already recommends). README's
npm snippet should match.
- F-2: 'default' drive appears 3x under mount root (multi-org flat
namespace artifact). Same behavior under local-daemon path.