11# @intx/storage-isogit
22
33Isomorphic-git backed implementation of ` ContextStore ` and
4- ` AuditStore ` . Each agent gets its own git repository on disk ;
4+ ` AuditStore ` . Each agent gets its own git repository in the host filesystem ;
55inference state lives on a working branch, the tool-authorization
66audit log lives on its own branch, and mail history lives in a
77dedicated audit store that commits each inbound and outbound
@@ -12,17 +12,81 @@ Consumed by `@intx/agent` for in-process persistence, and by
1212repositories that move between the hub and the sidecar as packs.
1313
1414``` ts
15- import { createIsogitStore } from " @intx/storage-isogit" ;
15+ import { createIsogitStore } from " @intx/storage-isogit/node " ;
1616
1717const store = await createIsogitStore (" ./tmp/agent-repo" , signer );
1818
1919// store implements both ContextStore and AuditStore -- hand it to
2020// the inference and tool layers as appropriate.
2121```
2222
23+ Node and Bun consumers use the ` /node ` entry point above. The package root is
24+ runtime-neutral and exports ` createIsogitStorage(runtime) ` for hosts that
25+ provide their own filesystem:
26+
27+ ``` ts
28+ import type { FsClient } from " isomorphic-git" ;
29+ import { createIsogitStorage } from " @intx/storage-isogit" ;
30+
31+ type IsogitRuntime = {
32+ fs: FsClient ;
33+ rename(oldPath : string , newPath : string ): Promise <void >;
34+ path: {
35+ join(... parts : string []): string ;
36+ relative(from : string , to : string ): string ;
37+ resolve(filepath : string ): string ;
38+ };
39+ flush? : () => Promise <void >;
40+ };
41+ ```
42+
43+ The storage layer derives its other filesystem operations from ` FsClient ` ,
44+ including recursive directory creation and removal, existence checks, and
45+ UTF-8 text reads. ` rename ` remains explicit because completed packs require an
46+ atomic publish primitive. Persistent backends can implement ` flush ` to make
47+ completed mutations durable before the API call resolves.
48+
49+ Audit and error record paths are append-only. Repeating a byte-identical
50+ record is an idempotent retry, including after an uncertain persistence
51+ failure; reusing the same path for different content is rejected. Mail commits
52+ reconcile an uncertain ref publication before the same store accepts another
53+ message, so a committed message cannot have its ordinal reused.
54+
55+ Browsers can use the included LightningFS IndexedDB adapter:
56+
57+ ``` ts
58+ import { createBrowserIsogitStorage } from " @intx/storage-isogit/browser" ;
59+
60+ const storage = createBrowserIsogitStorage (" agent-storage" );
61+ const store = await storage .createIsogitStore (" /agents/example" );
62+ ```
63+
64+ The browser adapter supplies isomorphic-git's Buffer compatibility, atomic
65+ rename, POSIX path operations, and IndexedDB-backed file storage. Each call to
66+ ` createBrowserIsogitStorage(name) ` claims a fresh volume and clears any prior
67+ contents for that name. Call it exactly once per name during a page or worker
68+ lifetime, then pass the returned storage object to every consumer. Reusing the
69+ same name from another factory call, bundle, tab, or worker is unsupported and
70+ may clear active data.
71+
72+ Browser storage is intentionally disposable: a page reload, tab close, or
73+ worker restart ends the logical session, and the next owner starts from an
74+ empty volume instead of attempting recovery. ` flush() ` writes the current
75+ filesystem state to IndexedDB, but does not promise that state will survive a
76+ new owner. IndexedDB is the storage medium, not a restart-persistence
77+ guarantee. Use absolute repository paths; relative browser paths resolve from
78+ ` / ` . Applications that require restart persistence must inject a durable
79+ runtime through the package root and own that runtime's recovery guarantees.
80+
2381The pack-send and pack-receive helpers (` createDeployPack ` ,
2482` createNegotiatedPack ` , ` applyPack ` , ` receivePackObjects ` ) produce
2583and consume the wire bytes that ` @intx/pack-transport ` chunks
2684across the WebSocket. A ` CommitSigner ` is optional but required
2785when the consumer needs every commit to carry a verifiable
2886signature.
87+
88+ Pack receivers flush an accepted pack before checkout or ref promotion. If a
89+ later ref or persistence operation fails, the call rejects but retains the
90+ pack because the ref update may already be observable. Callers must treat that
91+ error as an uncertain promotion outcome rather than assuming the ref is
92+ unchanged; whichever ref value is visible remains backed by durable objects.
0 commit comments