@guuey/fs 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Loqu, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,132 @@
1
+ # `@guuey/fs`
2
+
3
+ > Dev-guidance helper for GuueyFS — the per-(app, user, session) filesystem
4
+ > every agent hosted on [guuey.com](https://guuey.com) runs inside. There is
5
+ > no wrapper API: **plain `node:fs` on the three paths below IS the
6
+ > contract.** This package just tells you where they are.
7
+
8
+ ## Install
9
+
10
+ ```sh
11
+ npm install @guuey/fs
12
+ # or
13
+ pnpm add @guuey/fs
14
+ ```
15
+
16
+ ## The three paths
17
+
18
+ Every hosted agent invoke runs with three directories bound in, one per
19
+ layer:
20
+
21
+ | Helper | Layer | Read/write | Lifetime |
22
+ | -------------- | --------- | ------------------ | ---------------------------------------------------------------------------- |
23
+ | `homeDir()` | `home` | read-write | Durable, per (app, user) — survives restarts and new sessions. |
24
+ | `appDir()` | `app` | read-only | Shared across every user of the app; ships with the app, not per-user. |
25
+ | `sessionDir()` | `session` | read-write (= cwd) | Scratch for THIS turn's session. Pod-local — does not survive a pod restart. |
26
+
27
+ ```ts
28
+ import { homeDir, appDir, sessionDir } from "@guuey/fs";
29
+ import { readFile, writeFile, mkdir } from "node:fs/promises";
30
+ import { join } from "node:path";
31
+
32
+ // Durable per-user memory — plain node:fs, nothing else.
33
+ const memoryPath = join(homeDir(), "memories", "MEMORY.md");
34
+ await mkdir(join(homeDir(), "memories"), { recursive: true });
35
+ await writeFile(memoryPath, "User prefers dark mode.\n", { flag: "a" });
36
+ const memory = await readFile(memoryPath, "utf8").catch(() => undefined);
37
+
38
+ // Shared, read-only per-app assets your build ships with the agent.
39
+ const template = await readFile(join(appDir(), "templates", "welcome.md"), "utf8");
40
+
41
+ // Scratch space for this session — sessionDir() IS process.cwd(), so plain
42
+ // relative paths already resolve here.
43
+ await writeFile("draft.txt", "working notes for this turn\n");
44
+ // equivalent: join(sessionDir(), "draft.txt")
45
+ ```
46
+
47
+ Each helper throws a clear error if its env var isn't set — that's the
48
+ signal you're not running inside the guuey Router (`guuey dev` or the
49
+ hosted runtime). There's nothing to configure and nothing to catch
50
+ silently: either you're on a guuey pod and the paths are there, or you
51
+ aren't and the helper tells you so immediately.
52
+
53
+ ## Memory behavior — the part that matters
54
+
55
+ Once the durable filesystem is enabled for an environment (the GuueyFS
56
+ rollout — operator-gated per env, see Status below), this is the target
57
+ contract:
58
+
59
+ - **Signed-in users**: `homeDir()` is durable cross-session memory. Files an
60
+ agent writes today are there next week, from a different pod, after a
61
+ restart.
62
+ - **Guests (anonymous sessions)**: `homeDir()` is still a real, writable
63
+ directory — but it's backed by pod-local ephemeral scratch, not durable
64
+ storage. Nothing a guest writes survives past the pod's lifetime. This is
65
+ a deliberate platform boundary (guests never accumulate durable storage),
66
+ not a bug — don't build a feature that assumes guest `homeDir()` writes
67
+ persist.
68
+ - **`sessionDir()`** is pod-local scratch for every caller, guest or
69
+ signed-in — by contract, not a deferred feature. Don't put anything there
70
+ you need past the current session.
71
+
72
+ **Automatic recall is `claude-agent-sdk`-only today.** The three paths above
73
+ — including `homeDir()`'s durable-for-signed-in-users behavior — are the
74
+ same on every framework Guuey hosts. What's framework-scoped is the
75
+ Router's automatic recall: on `claude-agent-sdk`, the platform reads
76
+ `<home>/memories/MEMORY.md` before each turn and injects it into the
77
+ model's context for you, for free. On openai-agents-sdk and google-adk,
78
+ that automatic injection doesn't happen yet — an agent on those frameworks
79
+ can still read/write the same file with plain `node:fs` (as above), it just
80
+ has to do the reading itself. All-framework automatic recall arrives with
81
+ guuey's own memory MCP (a platform tool every framework calls over its
82
+ existing MCP channel). Separately: framework-native memory backends (e.g.
83
+ Google ADK's Vertex MemoryBank) are unsupported on Guuey — they store user
84
+ data outside guuey's deletion boundary, and there's no data-governance
85
+ policy for that yet.
86
+
87
+ Until the rollout reaches an environment, hosted agents there DO still get
88
+ `GUUEY_HOME_DIR`/`GUUEY_APP_DIR` — pointing at pod-local ephemeral storage.
89
+ Writes to `homeDir()` work, but nothing survives the pod: treat every layer
90
+ as session-lifetime until the durable filesystem is enabled for your
91
+ environment. The helpers' throw only signals you're outside the guuey
92
+ runtime entirely (no `guuey dev`, no hosted pod) — it is not a durability
93
+ signal.
94
+
95
+ ## What this package is NOT
96
+
97
+ - **Not a storage adapter.** There's no `FsSource`, no versioning/CoW
98
+ overlay, no read/write resolution logic to import. Base-path injection —
99
+ the Router hands you three real directories — won that design; a client
100
+ library on top of it would just be indirection.
101
+ - **Not a durability guarantee by itself.** The env vars are the contract;
102
+ whether `homeDir()` is backed by durable storage depends on whether the
103
+ durable filesystem is enabled for the environment AND whether the caller
104
+ is signed in (see Memory behavior above) — this package can't change
105
+ that, only report where the paths are.
106
+
107
+ ## Status
108
+
109
+ 🧪 **Developer preview (`0.x`).** The three-path shape (`home`/`app`/
110
+ `session`) and the env-var names (`GUUEY_HOME_DIR`, `GUUEY_APP_DIR`,
111
+ `process.cwd()`) are the actual production contract, not a preview of one —
112
+ code written against this package today keeps working unchanged when the
113
+ durable-filesystem rollout reaches your environment. What exists vs.
114
+ what's coming:
115
+
116
+ | Piece | Status |
117
+ | --------------------------------------------------- | ---------------------------------------------------------- |
118
+ | `homeDir()`/`appDir()`/`sessionDir()` helpers | ✅ shipped |
119
+ | Env-var contract (`GUUEY_HOME_DIR`/`GUUEY_APP_DIR`) | ✅ shipped |
120
+ | Durable per-user `home` (signed-in users) | 🔜 lands with the GuueyFS rollout (operator-gated per env) |
121
+ | Guest `home` = pod-local ephemeral | 🔜 lands with the GuueyFS rollout (operator-gated per env) |
122
+ | Per-user/per-app storage quotas | 🔜 enforced at the filesystem layer, not visible here |
123
+
124
+ Until the rollout reaches an environment, the durable backing is off there
125
+ (`GUUEY_FS_BASE` unset) — but hosted agents still get the env vars, pointing
126
+ at pod-local ephemeral storage: writes work, nothing survives the pod (see
127
+ Memory behavior above).
128
+
129
+ This package is optional sugar — three one-line env-var reads. You can
130
+ skip it entirely and read `process.env.GUUEY_HOME_DIR` /
131
+ `process.env.GUUEY_APP_DIR` / `process.cwd()` yourself; nothing here is
132
+ magic.
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @guuey/fs — a tiny dev-guidance helper for the GuueyFS 3-layer contract every
3
+ * hosted guuey agent runs inside. `homeDir()`/`appDir()`/`sessionDir()` just read
4
+ * the env vars the Router already injects (`GUUEY_HOME_DIR`/`GUUEY_APP_DIR`) plus
5
+ * `process.cwd()` — there is no wrapper API, no adapter, no storage abstraction.
6
+ * Plain `node:fs` on the three paths IS the contract. See README.md and
7
+ * docs/superpowers/specs/2026-07-20-guueyfs-slice4-design.md §6.
8
+ */
9
+ export { ENV_HOME_DIR, ENV_APP_DIR, homeDir, appDir, sessionDir } from "./roots.js";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @guuey/fs — a tiny dev-guidance helper for the GuueyFS 3-layer contract every
3
+ * hosted guuey agent runs inside. `homeDir()`/`appDir()`/`sessionDir()` just read
4
+ * the env vars the Router already injects (`GUUEY_HOME_DIR`/`GUUEY_APP_DIR`) plus
5
+ * `process.cwd()` — there is no wrapper API, no adapter, no storage abstraction.
6
+ * Plain `node:fs` on the three paths IS the contract. See README.md and
7
+ * docs/superpowers/specs/2026-07-20-guueyfs-slice4-design.md §6.
8
+ */
9
+ export { ENV_HOME_DIR, ENV_APP_DIR, homeDir, appDir, sessionDir } from "./roots.js";
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Env-var names the Router injects so agent code reaches the home/app layers
3
+ * portably. This package's OWN copy (trivial string literals — not imported,
4
+ * so the published `@guuey/fs` package has zero non-devDependency deps and
5
+ * cannot depend on the platform-private contract package). Sync sites if
6
+ * these ever change: `backend/libs/fs-contract/src/contract.ts` (the
7
+ * platform-internal source of truth) and `oss/packages/host/src/frameworks/
8
+ * claude-options.ts:41-45` (same OSS-legality constraint, same literals).
9
+ */
10
+ export declare const ENV_HOME_DIR = "GUUEY_HOME_DIR";
11
+ export declare const ENV_APP_DIR = "GUUEY_APP_DIR";
12
+ /** The user's durable memory layer root (reads GUUEY_HOME_DIR, Router-injected). */
13
+ export declare function homeDir(env?: NodeJS.ProcessEnv): string;
14
+ /** The app's shared read-only layer root (reads GUUEY_APP_DIR, Router-injected). */
15
+ export declare function appDir(env?: NodeJS.ProcessEnv): string;
16
+ /** The per-session working dir = the process cwd (the Router sets cwd = sessionDir). */
17
+ export declare function sessionDir(cwd?: () => string): string;
18
+ //# sourceMappingURL=roots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roots.d.ts","sourceRoot":"","sources":["../src/roots.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,mBAAmB,CAAC;AAC7C,eAAO,MAAM,WAAW,kBAAkB,CAAC;AAE3C,oFAAoF;AACpF,wBAAgB,OAAO,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAEpE;AAED,oFAAoF;AACpF,wBAAgB,MAAM,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAEnE;AAED,wFAAwF;AACxF,wBAAgB,UAAU,CAAC,GAAG,GAAE,MAAM,MAAoB,GAAG,MAAM,CAElE"}
package/dist/roots.js ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Env-var names the Router injects so agent code reaches the home/app layers
3
+ * portably. This package's OWN copy (trivial string literals — not imported,
4
+ * so the published `@guuey/fs` package has zero non-devDependency deps and
5
+ * cannot depend on the platform-private contract package). Sync sites if
6
+ * these ever change: `backend/libs/fs-contract/src/contract.ts` (the
7
+ * platform-internal source of truth) and `oss/packages/host/src/frameworks/
8
+ * claude-options.ts:41-45` (same OSS-legality constraint, same literals).
9
+ */
10
+ export const ENV_HOME_DIR = "GUUEY_HOME_DIR";
11
+ export const ENV_APP_DIR = "GUUEY_APP_DIR";
12
+ /** The user's durable memory layer root (reads GUUEY_HOME_DIR, Router-injected). */
13
+ export function homeDir(env = process.env) {
14
+ return requireRoot(env, ENV_HOME_DIR);
15
+ }
16
+ /** The app's shared read-only layer root (reads GUUEY_APP_DIR, Router-injected). */
17
+ export function appDir(env = process.env) {
18
+ return requireRoot(env, ENV_APP_DIR);
19
+ }
20
+ /** The per-session working dir = the process cwd (the Router sets cwd = sessionDir). */
21
+ export function sessionDir(cwd = process.cwd) {
22
+ return cwd();
23
+ }
24
+ function requireRoot(env, name) {
25
+ const value = env[name];
26
+ if (!value) {
27
+ throw new Error(`${name} is not set — the guuey agent runtime injects it. Run via \`guuey dev\` or the hosted runtime.`);
28
+ }
29
+ return value;
30
+ }
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@guuey/fs",
3
+ "version": "0.1.0",
4
+ "description": "GuueyFS dev-guidance helper — homeDir()/appDir()/sessionDir() read the three env-var/cwd paths the guuey Router injects into every hosted agent. No wrapper API: plain node:fs on the returned paths IS the contract.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "files": [
10
+ "dist",
11
+ "README.md"
12
+ ],
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js",
17
+ "default": "./dist/index.js"
18
+ }
19
+ },
20
+ "devDependencies": {
21
+ "@types/node": "^24.0.0",
22
+ "typescript": "^5.0.0",
23
+ "vitest": "^3.0.0"
24
+ },
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "keywords": [
29
+ "guuey",
30
+ "filesystem",
31
+ "vfs",
32
+ "layers",
33
+ "agent"
34
+ ],
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "git+https://github.com/withguuey/guuey-sdks.git",
38
+ "directory": "packages/fs"
39
+ },
40
+ "homepage": "https://guuey.com",
41
+ "bugs": {
42
+ "url": "https://github.com/loqu-co/guuey/issues"
43
+ },
44
+ "scripts": {
45
+ "build": "tsc -p tsconfig.build.json",
46
+ "dev": "tsc --watch",
47
+ "typecheck": "tsc --noEmit",
48
+ "test": "vitest run",
49
+ "test:watch": "vitest"
50
+ }
51
+ }