171 lines
7.3 KiB
Markdown
171 lines
7.3 KiB
Markdown
# User Folder Layout
|
|
|
|
## Overview
|
|
|
|
Every authenticated user gets a personal folder at `data/users/{userId}/`.
|
|
This folder is the user's private, cross-task workspace. Unlike a job's
|
|
ephemeral workspace (which lives under `{worktree_dir}/local/{taskId}/` and is
|
|
tied to a single run), the user folder **persists indefinitely** across tasks,
|
|
sessions, and server restarts.
|
|
|
|
The primary use-cases are:
|
|
- Storing reusable browser macros (`browser-macros/`) that any of your tasks can invoke via `RunUserScript`.
|
|
- Keeping template files and reference documents you want agents to access without uploading them every time.
|
|
- Holding auto-generated recordings of browser sessions so you can review or convert them later.
|
|
- Managing saved browser login sessions (`browser-sessions/`) that macros can use.
|
|
|
|
Access is **owner-only**: the REST API enforces that only the owner (or an
|
|
admin) can read, write, or delete files inside the folder. The directory is
|
|
created on first login and is never shared between accounts.
|
|
|
|
---
|
|
|
|
## Subdirectories
|
|
|
|
### `browser-macros/`
|
|
|
|
**Playwright-based browser automation scripts.** Launches Chromium. Signature: `main({ context, params })`.
|
|
|
|
> **Retired (2026-06):** the former `scripts/` (plain Node) and `templates/`
|
|
> subdirectories were removed. Reusable procedures/boilerplate belong in
|
|
> **Skills**; ad-hoc code runs via the agent's **Bash** tool. Existing files
|
|
> remain on disk but are no longer listed or runnable.
|
|
|
|
Generated automatically by the **Save as Script** button in the recordings panel. Can also be written manually in the UI. The agent runs them via `RunUserScript({ name })`.
|
|
|
|
If a `session_profile_id` is declared in the frontmatter, the corresponding saved browser session (from `browser-sessions/`) is loaded automatically.
|
|
|
|
**Self-healing patches**: when a macro fails, the agent auto-enables the BrowseWeb recorder; on task completion a candidate patch is staged as `browser-macros/{name}.next.js`. The Diff review pane lets you accept or reject it. See [Self-Healing Patches](#self-healing-script-patches) below.
|
|
|
|
### `recordings/`
|
|
|
|
Browser-session recordings produced by `BrowseWeb` when the `record_to`
|
|
parameter is set. Each recording lands here as `{name}.json` once the session
|
|
ends. The file contains an ordered list of timestamped actions.
|
|
|
|
You never write here directly — the server writes recordings automatically.
|
|
The **User Folder → recordings/** panel lets you view recordings and convert them
|
|
to browser macros via **Save as Script** (saves to `browser-macros/`).
|
|
|
|
### `browser-sessions/`
|
|
|
|
**Virtual subdir (no actual filesystem directory).** Manages saved browser login
|
|
profiles — cookies and storage state captured via noVNC (CAPTCHA/2FA bypass).
|
|
Sessions are encrypted with a per-user key.
|
|
|
|
Managed from the **User Folder → browser-sessions/** panel in the UI:
|
|
1. Click "Add site session", enter the URL and a label.
|
|
2. Log in inside the noVNC window that opens.
|
|
3. Click Save — the encrypted storage state is written to the DB.
|
|
|
|
Browser macros reference a session by `session_profile_id: <N>` in their frontmatter.
|
|
|
|
### `trash/`
|
|
|
|
Soft-deleted scripts, macros, templates, and recordings are moved here rather than
|
|
immediately erased. Files in `trash/` accumulate with a timestamp prefix:
|
|
`{YYYYMMDD-HHMMSS}-{rand4hex}-{name}`. Restore by copying the content back to the
|
|
original subdir via the editor.
|
|
|
|
### `memory/`
|
|
|
|
Persistent memory entries managed by the `UpdateUserMemory` and `ReadUserMemory` tools.
|
|
|
|
**`MEMORY.md`** (index file) — automatically injected into the agent's system prompt at the start of every movement. It contains one line per entry:
|
|
|
|
```
|
|
- [preferred-language](preferred-language.md) — User prefers Japanese output
|
|
- [project-stack](project-stack.md) — Tech stack for the main project
|
|
```
|
|
|
|
**Individual fact files** (`{name}.md`) — each has YAML frontmatter followed by a plain Markdown body:
|
|
|
|
```
|
|
---
|
|
name: preferred-language
|
|
description: User prefers Japanese output
|
|
type: user
|
|
---
|
|
Always respond in Japanese unless the user explicitly asks for another language.
|
|
```
|
|
|
|
**Note:** `MEMORY.md` is agent-managed via `UpdateUserMemory`. Manual edits to the index file are tolerated but may cause duplicate lines if you change the link format `- [name](file.md)`.
|
|
|
|
**Memory types:**
|
|
|
|
| Type | Intended use |
|
|
|------|-------------|
|
|
| `user` | Long-term user preferences, standing instructions |
|
|
| `feedback` | Corrections the user has given (e.g. "don't do X") |
|
|
| `project` | Project-specific facts (stack, conventions, key files) |
|
|
| `reference` | Reference data (URLs, credentials patterns, external IDs) |
|
|
|
|
---
|
|
|
|
## AGENTS.md
|
|
|
|
`data/users/{userId}/AGENTS.md` (at the top level of your user folder, not
|
|
inside a subdirectory) is your **personal agent instruction file**. Whenever
|
|
the orchestrator starts a task on your behalf it reads this file and injects
|
|
its contents into the agent's system prompt, before any piece-specific
|
|
instructions.
|
|
|
|
Edit it from the **Settings → Agent instructions** panel or with any text
|
|
editor — the agent picks up the latest version at the start of each task.
|
|
|
|
---
|
|
|
|
## Browser-Macro Format
|
|
|
|
### Browser macros (`browser-macros/`)
|
|
|
|
```js
|
|
---
|
|
description: "Log in and navigate to the dashboard"
|
|
params:
|
|
- name: username
|
|
type: string
|
|
- name: password
|
|
type: string
|
|
session_profile_id: 1
|
|
---
|
|
async function main({ context, params }) {
|
|
const page = await context.newPage();
|
|
try {
|
|
await page.goto('https://example.com/login');
|
|
await page.locator('#username').fill(params.username);
|
|
await page.locator('#password').fill(params.password);
|
|
await page.locator('button[type=submit]').click();
|
|
} finally {
|
|
await page.close();
|
|
}
|
|
}
|
|
module.exports = main;
|
|
```
|
|
|
|
Invocation: `RunUserScript({ name: 'login', kind: 'browser-macro', params: { username: '...', password: '...' } })`
|
|
|
|
Full field reference, parameter passing, and session-profile selection are documented in [docs/tools/runuserscript.md](tools/runuserscript.md).
|
|
|
|
---
|
|
|
|
## Self-Healing Script Patches
|
|
|
|
When a `RunUserScript` call with `kind: 'browser-macro'` fails because a selector no longer matches the page, the agent automatically enables the BrowseWeb recorder. The recorded interactions are compiled into a candidate patch at `browser-macros/{name}.next.js`.
|
|
|
|
The Diff review pane in **User Folder → browser-macros/** compares the current `.js` with the `.next.js` candidate and asks you to approve or reject the patch. On approval the server atomically replaces `{name}.js`. On rejection the staging file is discarded.
|
|
|
|
This means the live `browser-macros/` folder always contains only reviewed, approved code.
|
|
|
|
---
|
|
|
|
## Permissions and Privacy
|
|
|
|
The `data/users/{userId}/` directory is created with mode `0700` (owner read/write/execute only) at the filesystem level. At the API level every endpoint under `/api/users/me/` requires a valid session cookie and verifies that the authenticated user's ID matches the folder being accessed. Admin users can access any user's folder.
|
|
|
|
No other user — including users in the same organisation — can list or read your scripts, macros, templates, recordings, or AGENTS.md.
|
|
|
|
### Auth-disabled mode (local dev only)
|
|
|
|
When the `auth:` section is absent from `config.yaml` (`authActive=false`), the User Folder API injects a synthetic `{ id: 'local', role: 'user' }` user, so all operations go to `data/users/local/`. Production deployments should always run with auth enabled.
|