@turmind/halo 1.6.3 → 1.6.4
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/README.md +58 -67
- package/admin-out/404.html +1 -1
- package/admin-out/_next/static/chunks/989-5d7743ff56d00dd7.js +1 -0
- package/admin-out/_next/static/chunks/app/page-8881b4f87a3d5ae8.js +1 -0
- package/admin-out/index.html +1 -1
- package/admin-out/index.txt +4 -4
- package/bin/halo.js +4 -0
- package/bundled-docs/design/architecture.md +1 -1
- package/bundled-docs/design/canvas-extensions.md +2 -2
- package/bundled-docs/design/observability.md +7 -5
- package/bundled-docs/design/storage.md +8 -5
- package/bundled-docs/design/wechat.md +1 -1
- package/bundled-docs/dev/add-model-provider.md +2 -1
- package/bundled-docs/dev/api.md +2 -1
- package/bundled-docs/dev/deploy.md +114 -26
- package/bundled-docs/dev/desktop-packaging.md +13 -1
- package/bundled-docs/dev/env.md +3 -3
- package/bundled-docs/dev/logging.md +13 -2
- package/bundled-docs/dev/tools.md +2 -2
- package/bundled-docs/guide/agents.md +2 -2
- package/bundled-docs/guide/cli.md +20 -8
- package/bundled-docs/guide/getting-started.md +13 -5
- package/bundled-docs/guide/workspace.md +2 -0
- package/bundled-docs/requirements/agent.md +1 -1
- package/bundled-docs/requirements/explorer.md +14 -2
- package/bundled-docs/requirements/settings.md +2 -2
- package/dist/index.js +2565 -1449
- package/package.json +3 -2
- package/templates/models/gemini.yaml +93 -0
- package/admin-out/_next/static/chunks/989-ddba0eb72566da23.js +0 -1
- package/admin-out/_next/static/chunks/app/page-7ffcbddb49dc56c4.js +0 -1
- /package/admin-out/_next/static/{k5zuJrivSdbaPifBatwdr → kfp1cMc36J6hjZ06L9mm-}/_buildManifest.js +0 -0
- /package/admin-out/_next/static/{k5zuJrivSdbaPifBatwdr → kfp1cMc36J6hjZ06L9mm-}/_ssgManifest.js +0 -0
package/bundled-docs/dev/env.md
CHANGED
|
@@ -52,8 +52,8 @@ nohup node dist/index.js >> /dev/null 2>&1 & # HALO_PASSWORD read from env/con
|
|
|
52
52
|
|
|
53
53
|
- Node.js ≥ 22 (better-sqlite3 native binding is bound to v22)
|
|
54
54
|
- pnpm 11 (pinned by the root `packageManager`; `corepack enable` picks it up)
|
|
55
|
-
- AWS credentials
|
|
56
|
-
- bubblewrap (`sudo apt install bubblewrap`) — OS-level sandbox for non-full access levels on Linux (macOS uses the built-in Seatbelt). Without one, only app-level path validation is active and `shell_exec` is blocked for non-full sessions
|
|
55
|
+
- AWS credentials (`~/.aws/credentials`, env vars or an instance role) — only for the Bedrock providers; any other provider just needs its API key
|
|
56
|
+
- bubblewrap (`sudo apt install bubblewrap`) — OS-level sandbox for non-full access levels on Linux (macOS uses the built-in Seatbelt). Without one, only app-level path validation is active and `shell_exec` is blocked for non-full sessions. On Ubuntu 23.10+ / 24.04 AppArmor blocks it (`bwrap: setting up uid map: Permission denied`) until you add a profile — see [deploy.md](deploy.md#bubblewrap-on-ubuntu-2310-and-2404-apparmor)
|
|
57
57
|
|
|
58
58
|
### nvm PATH
|
|
59
59
|
|
|
@@ -118,7 +118,7 @@ Source: `packages/server/src/config.ts`
|
|
|
118
118
|
| `HALO_A2A_ROOT` | the user's home | — | Base dir A2A exposes workspaces under: a workspace `<base>/A/B` with `.halo/agent-card.json` is served at `/a2a/A/B` (see [design/a2a.md](../design/a2a.md)); workspaces outside it can't be exposed |
|
|
119
119
|
| `HALO_A2A_PUBLIC_URL` | (none) | `settings.yaml general.a2a.public_url` | This server's A2A origin as peers see it (no trailing slash), used for the agent card's interface URL and as the default push-webhook base. In agentcore-a2a mode: the runtime's invoke URL (`…/runtimes/<escaped ARN>/invocations`) |
|
|
120
120
|
| `HALO_A2A_ACCESS` | `workspace` | — | agentcore-a2a mode only: access level of every A2A session — `workspace` \| `full` \| `readonly`; anything else is a boot error |
|
|
121
|
-
| `HALO_DEFAULT_PROVIDER` | (none) | — | Read by `halo setup --non-interactive`: binds
|
|
121
|
+
| `HALO_DEFAULT_PROVIDER` | (none) | — | Read by `halo setup --non-interactive`: binds every built-in agent to this provider id (and its default model) and, for each of its env-backed keys whose variable is set, writes the `<<NAME>>` placeholder into `settings.yaml` (Bedrock excepted). An unknown id only prints a warning |
|
|
122
122
|
| `HALO_CLI` | `halo` (`halo.cmd` on Windows) | — | `halo` cli executable that cron runs and the evolution wrapper spawn — a dev override |
|
|
123
123
|
| `HALO_VERSION` | `dev` | — | Version string reported by `GET /api/health` and the cli; stamped by the bundle / desktop launcher, so normally not set by hand |
|
|
124
124
|
| `HALO_PROMPT` | (none) | — | `plain` makes `halo setup` use numbered-menu prompts instead of the raw-mode TUI |
|
|
@@ -15,18 +15,29 @@ Any `?token=…` value in a message is replaced with `?token=<redacted>` before
|
|
|
15
15
|
|
|
16
16
|
## Log locations
|
|
17
17
|
|
|
18
|
-
One file for the whole server: `~/.halo/global/logs/server.log`. A single server process serves many workspaces, so there is no per-workspace log. Cron runs and evolution runs keep their own logs under `~/.halo/global/logs/{cron,evo}/`. `halo server start -d` additionally captures the process's stdout/stderr in `~/.halo/logs/server.log`
|
|
18
|
+
One file for the whole server: `~/.halo/global/logs/server.log`. A single server process serves many workspaces, so there is no per-workspace log. Cron runs and evolution runs keep their own logs under `~/.halo/global/logs/{cron,evo}/`. `halo server start -d` additionally captures the process's stdout/stderr in `~/.halo/logs/server.log` — via the systemd user unit's `StandardOutput=append:` on Linux with systemd, otherwise via the built-in supervisor, which adds its `[respawn]` lines — that is the file `halo server logs` tails. A system unit's stdout goes to the journal (`journalctl -u <unit>`).
|
|
19
19
|
|
|
20
20
|
## Log format
|
|
21
21
|
|
|
22
22
|
```
|
|
23
|
-
time=2026-04-19T10:30:00.000Z level=info [Server]
|
|
23
|
+
time=2026-04-19T10:30:00.000Z level=info [Server] Halo 1.6.3 listening on port 9527 on all network interfaces — local: http://localhost:9527
|
|
24
24
|
time=2026-04-19T10:30:01.234Z level=error [WS] Chat error: ThrottlingException
|
|
25
25
|
time=2026-04-19T10:30:02.567Z level=warn [SessionManager] Context overflow, auto-compacting...
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
Every line is logfmt-flavored: `time=<ISO timestamp> level=<debug|info|warn|error> <message>`; the message keeps its `[Module]` prefix.
|
|
29
29
|
|
|
30
|
+
### Always-shown lines
|
|
31
|
+
|
|
32
|
+
The startup banner bypasses the level gate: `logAlways()` (`logger.ts`) writes it straight to stderr whatever `general.logging.level` is, so a foreground `halo server start` at the default `warn` still shows that it came up. It is also written to the log file / OTel as an `info` line, but only when `info` passes the gate. The banner names the real bound address (`formatListenBanner()` in `listen-banner.ts`). The server passes no hostname, so it binds every interface, and the banner says so in two lines:
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
[Server] Halo 1.6.3 listening on port 9527 on all network interfaces — local: http://localhost:9527
|
|
36
|
+
[Server] Reachable from the network: allow the port only from trusted sources, or put a TLS reverse proxy in front
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
A specific bound address prints one line, `[Server] Halo <version> listening on http://<addr>:<port>` (IPv6 bracketed). AgentCore mode prints only the first line. Lines printed before `initLogger()` (setup / template-refresh notices, the source-run-only `monorepo root … not found` warning) aren't filtered either, and they never reach the log file.
|
|
40
|
+
|
|
30
41
|
## Rotation
|
|
31
42
|
|
|
32
43
|
When the log file exceeds the cap:
|
|
@@ -132,11 +132,11 @@ Each session carries `accessLevel: 'readonly' | 'workspace' | null` (persisted i
|
|
|
132
132
|
|
|
133
133
|
`view_image` is additionally gated on `capabilities.image` (see its section above). Models without vision support get the same lists minus `view_image` — so a non-vision model on `readonly` ends up with 4 tools, not 5.
|
|
134
134
|
|
|
135
|
-
OS sandbox backend per platform — `getSandboxBackend()` in `sandbox.ts` returns `'bwrap' | 'seatbelt' | null` after the boot probe (`initBwrapCheck()`), logged at startup as `[Server] OS sandbox: …` and exposed as `sandbox` on `GET /api/health`:
|
|
135
|
+
OS sandbox backend per platform — `getSandboxBackend()` in `sandbox.ts` returns `'bwrap' | 'seatbelt' | null` after the boot probe (`initBwrapCheck()`), logged at startup as `[Server] OS sandbox: …` (`info` level, so hidden at the default `warn`). When the probe found bwrap missing (ENOENT) or unable to create namespaces, the server instead warns once at boot: `[Server] OS sandbox unavailable (<reason>) — workspace/readonly sessions get no shell_exec. Fix: <hint>` (`sudo apt install bubblewrap`, or the AppArmor profile in [deploy.md](deploy.md#bubblewrap-on-ubuntu-2310-and-2404-apparmor)). `halo cli` / `tui` print the same line (`[cli]` tag) only for a `--access workspace|readonly` session; the probe itself never prints (`getSandboxUnavailableReason()` / `sandboxUnavailableWarning()` in `sandbox.ts`). Also exposed as `sandbox` on `GET /api/health`:
|
|
136
136
|
|
|
137
137
|
| Platform | `shell_exec` | File tools | Dependency |
|
|
138
138
|
|---|---|---|---|
|
|
139
|
-
| Linux | bwrap | bwrap | `bubblewrap` (`apt install bubblewrap`); the probe runs a real sandboxed no-op, so an install that can't create namespaces (Ubuntu 24.04 AppArmor userns restriction) counts as unavailable |
|
|
139
|
+
| Linux | bwrap | bwrap | `bubblewrap` (`apt install bubblewrap`); the probe runs a real sandboxed no-op, so an install that can't create namespaces (Ubuntu 23.10+ / 24.04 AppArmor userns restriction: `bwrap: setting up uid map: Permission denied`) counts as unavailable — fix in [deploy.md](deploy.md#bubblewrap-on-ubuntu-2310-and-2404-apparmor) |
|
|
140
140
|
| macOS | Seatbelt (`/usr/bin/sandbox-exec -p <profile>`) | in-process, behind `assertPathAllowed` | none — ships with macOS (Apple marks it deprecated, but it's present on every release). The probe runs `sandbox-exec -p '(version 1)(allow default)' /usr/bin/true` |
|
|
141
141
|
| Windows | none | none | — see below |
|
|
142
142
|
|
|
@@ -6,7 +6,7 @@ The agent is Halo's core abstraction: personality (AGENT.md) + config (agent.yam
|
|
|
6
6
|
|
|
7
7
|
| Kind | Description |
|
|
8
8
|
|---|---|
|
|
9
|
-
| Built-in | Server-shipped agents (`default`, `executor`, `deep-executor` + the internal
|
|
9
|
+
| Built-in | Server-shipped agents (`default`, `executor`, `deep-executor` + the internal ones such as `__evo_agent__` / `__score__` / `__apply_agent__`). Live under `~/.halo/global/agents/<id>/`. **Force-overwritten on every server startup** — local edits to these files will be lost on the next start. To customize: copy into the workspace scope (workspace replaces global) and edit there. |
|
|
10
10
|
| Global | Any other agent under `~/.halo/global/agents/<id>/`, e.g. one you created via the admin UI. Shared across projects. Never overwritten by the server. |
|
|
11
11
|
| Workspace | `<project>/.halo/agents/<id>/`, private to the current project; same-id workspace wins over global. Override is **whole-folder**: the workspace agent folder replaces the global one entirely, so copy *both* `agent.yaml` and `AGENT.md` when customizing — a folder with only `AGENT.md` has no model config and won't load. |
|
|
12
12
|
|
|
@@ -113,7 +113,7 @@ Top-right `Test` button:
|
|
|
113
113
|
|
|
114
114
|
Better than the old built-in test chat — it has full workspace tools + session persistence.
|
|
115
115
|
|
|
116
|
-
Internal agents (`internal: true`, e.g. self-evolution agents) have no Test button and never appear in the chat agent selector, the Cron agent picker or `/session new`'s default pick — they're delegated to by other agents, never driven directly. They remain editable in the management sidebar's collapsed **Internal** group.
|
|
116
|
+
Internal agents (`internal: true`, e.g. self-evolution agents) have no Test button and never appear in the chat agent selector, the Cron agent picker or `/session new`'s default pick — they're delegated to by other agents, never driven directly. They remain editable in the management sidebar's collapsed **Internal** group.
|
|
117
117
|
|
|
118
118
|
## Delete
|
|
119
119
|
|
|
@@ -110,6 +110,8 @@ git diff HEAD~1 | halo cli -w /path/to/review-ws "review this diff"
|
|
|
110
110
|
halo cli "check for issues" && echo "OK" || echo "FAILED"
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
+
When stdin is not a TTY, piped input is appended after the positional prompt. With a positional prompt, stdin is only read if its first data arrives within 0.5 s — then to EOF, however long it takes. Otherwise it's ignored, so an open-but-idle stdin (scripts, CI, cron, `ssh host 'halo cli …'` without `-t`) no longer hangs the run. A producer that takes longer than that to print anything gets ignored too; capture it first (`out=$(slow-cmd); halo cli "summarize" <<<"$out"`). Without a positional prompt, stdin *is* the prompt: `halo cli` waits for EOF, and after 1 s of silence prints one `waiting for the prompt on stdin` hint to stderr.
|
|
114
|
+
|
|
113
115
|
## TUI Mode (interactive)
|
|
114
116
|
|
|
115
117
|
```bash
|
|
@@ -233,13 +235,22 @@ Normally run for you by `/extension models`, which downloads the hub's newest `m
|
|
|
233
235
|
## Server Mode (background daemon)
|
|
234
236
|
|
|
235
237
|
`halo server start|stop|restart|status|logs` manages a local server from the
|
|
236
|
-
same binary. `start -d` runs it
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
238
|
+
same binary. On Linux with systemd, `start -d` (and `restart`) runs it as the
|
|
239
|
+
user unit `~/.config/systemd/user/halo.service`, written and enabled for you
|
|
240
|
+
with linger on, so it starts at boot and comes back 5s after a crash. Your
|
|
241
|
+
shell's environment is saved to `~/.halo/secrets/server.env` for it. A system
|
|
242
|
+
unit that already runs `halo server start` as you is started instead.
|
|
243
|
+
`stop|restart|status` on a unit-run server go through `systemctl`, and print
|
|
244
|
+
the `sudo systemctl …` line when a system unit needs it. See
|
|
245
|
+
[dev/deploy.md](../dev/deploy.md#option-c-systemd-for-the-npm-install).
|
|
246
|
+
|
|
247
|
+
Elsewhere (macOS, Windows, Linux without systemd, a redirected HOME, an
|
|
248
|
+
unreachable user manager) `start -d` runs it in the background **with a bounded
|
|
249
|
+
respawn supervisor**: the detached process supervises the server and brings it
|
|
250
|
+
back on a crash (non-zero exit, or a kill by anything other than
|
|
251
|
+
SIGTERM/SIGINT), at most 5 times per 5 minutes with a 2s pause, logging each
|
|
252
|
+
decision as `[respawn] …` into `~/.halo/logs/server.log`. `halo server stop` is
|
|
253
|
+
recognized as intentional and never respawns. Full policy in
|
|
243
254
|
[dev/deploy.md](../dev/deploy.md#crash-semantics--why-restarton-failure-is-load-bearing).
|
|
244
255
|
|
|
245
256
|
## AgentCore runtime (`halo agentcore`)
|
|
@@ -274,7 +285,8 @@ packages/cli/
|
|
|
274
285
|
src/
|
|
275
286
|
index.ts — Entry: subcommand dispatch (tui/cli/agents/sessions/server/setup/upgrade/acp), SIGINT/SIGTERM handling
|
|
276
287
|
harness.ts — Shared agent harness wrapping SessionManager
|
|
277
|
-
server-supervisor.ts — Respawn policy for `halo server start -d`
|
|
288
|
+
server-supervisor.ts — Respawn policy for `halo server start -d` off systemd
|
|
289
|
+
server-systemd.ts — Linux systemd path: user unit + env snapshot, unit routing for stop/restart/status
|
|
278
290
|
cli.ts — Non-interactive: stdin/args → agent → stdout → exit
|
|
279
291
|
tui.tsx — Interactive entry: mounts the ink app
|
|
280
292
|
tui/
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
What to do the first time you open Halo.
|
|
4
4
|
|
|
5
|
+
Not installed yet? The [README Install section](../../../README.md#install) covers the three things a fresh box trips on: Node 22 first (Ubuntu 24.04's own `nodejs` is 18 and won't work), `sudo npm install -g` with a system-wide Node, and keeping **Configure…** (the default) at `halo setup`'s key step before binding the default agent.
|
|
6
|
+
|
|
5
7
|
## Log in
|
|
6
8
|
|
|
7
9
|
Open `http://localhost:9527` (or your deployment URL) in a browser and enter the password.
|
|
@@ -14,6 +16,8 @@ Open `http://localhost:9527` (or your deployment URL) in a browser and enter the
|
|
|
14
16
|
|
|
15
17
|
After login, you land in the workspace. A URL with `?folder=/abs/path` opens that directory directly; without `?folder`, Halo reopens the last workspace you used, or your home directory if there isn't one — everything still works.
|
|
16
18
|
|
|
19
|
+
`halo cli` / `halo tui` use the current directory as the workspace, so running them in `$HOME` makes `~/.halo` itself a workspace (`halo.db`, `sessions/`, `memory/`, `canvas/` appear next to `global/` and `secrets/`). `cd` into a project, or pass `-w <dir>`, to keep them apart.
|
|
20
|
+
|
|
17
21
|
The Explorer top bar has two ways to switch workspace:
|
|
18
22
|
- **Type an absolute path** + Enter — invalid paths raise an error
|
|
19
23
|
- **Click the 📁🔍 button** — opens a VS Code-style directory picker: single click to select, double click to enter, ArrowUp to go up, 🏠 for home, paste paths into the top input
|
|
@@ -65,21 +69,25 @@ After `halo setup`:
|
|
|
65
69
|
```
|
|
66
70
|
~/.halo/
|
|
67
71
|
├── global/ ← server-managed, see overwrite policy below
|
|
72
|
+
│ ├── .template-version ← seed version stamp, compared on every start
|
|
68
73
|
│ ├── INSTRUCTIONS.md ← refreshed on upgrade
|
|
69
74
|
│ ├── prompts/{bootstrap,all,root}/ ← refreshed on upgrade
|
|
70
75
|
│ ├── models/<provider>.yaml ← refreshed on upgrade
|
|
71
76
|
│ ├── docs/ ← refreshed on upgrade (bundled platform docs)
|
|
72
77
|
│ ├── agents/ ← built-in ids refreshed; user-added ones untouched
|
|
73
|
-
│
|
|
74
|
-
|
|
78
|
+
│ ├── skills/ ← built-in ids refreshed; user-added ones untouched
|
|
79
|
+
│ ├── aliases.yaml ← command aliases, seeded once, never overwritten
|
|
80
|
+
│ └── extensions/ ← preview extensions, created empty
|
|
81
|
+
└── secrets/ ← mode 700, files 600; never overwritten after first creation
|
|
75
82
|
├── config.yaml ← leaf-merged: new server knobs added, existing values kept
|
|
76
|
-
|
|
77
|
-
└── channels/channels.db ← per-channel account state
|
|
83
|
+
└── settings.yaml ← created empty if missing; otherwise untouched
|
|
78
84
|
```
|
|
79
85
|
|
|
86
|
+
The first `halo server start` adds the runtime state: `global/{a2a,cron,evo,runs}.db`, `global/logs/`, `global/models.d/`, `global/server.lock`, `global/server.stop` (after a stop), and `secrets/channels/channels.db` (per-channel account state).
|
|
87
|
+
|
|
80
88
|
**When does "refreshed on upgrade" actually run?** `halo setup` always re-runs the seed; the server's startup check — and the same check at the start of `halo cli` / `halo tui` — also re-runs it automatically when `~/.halo/global/.template-version` is behind the bundled `TEMPLATE_VERSION`. So the routine flow `halo upgrade && halo server restart` is enough — no need to remember `halo setup` — and a CLI-only user just runs `halo cli` / `halo tui` after `halo upgrade`.
|
|
81
89
|
|
|
82
|
-
**Server-refreshed**: `INSTRUCTIONS.md`, `prompts/`, `models/`, `docs/`, the built-in agent ids (`default`, `executor`, `deep-executor
|
|
90
|
+
**Server-refreshed**: `INSTRUCTIONS.md`, `prompts/`, `models/`, `docs/`, the built-in agent ids (`default`, `executor`, `deep-executor` plus the internal agents), and the built-in skill ids (`agent`, `skill`, `workspace`, `cron`, `send-file`, `self`, `aws-knowledge`, `web-search`, `halo`, `extension`). To customize one, copy it into the workspace scope (`<project>/.halo/...`) — workspace replaces global at runtime.
|
|
83
91
|
|
|
84
92
|
**Never overwritten**: anything else under `agents/` or `skills/` (your own creations), and everything under `secrets/`.
|
|
85
93
|
|
|
@@ -64,6 +64,8 @@ VS Code style:
|
|
|
64
64
|
|
|
65
65
|
Right-click menu: New File / New Folder / Open in Integrated Terminal / Reveal in File Manager (desktop app only) / Open to the Side / Download / Rename / Delete / Open as Workspace (folders).
|
|
66
66
|
|
|
67
|
+
**Download a folder**: right-click a folder (or the empty area for the whole workspace) → Download. A confirm shows the approximate size and file count; `node_modules`, `.git` and other build/cache folders are left out unless you tick the checkbox, and `.env` files, secrets (plus common credential stores: ~/.kube, cloud CLI configs, shell histories) and Halo's session data are always left out. You get one `<folder>.zip`; anything left out is listed in `_halo-excluded.txt` inside it. Folders with more than 200,000 files can't be downloaded in one go — pick a subfolder.
|
|
68
|
+
|
|
67
69
|
**Quick Open**: `Cmd/Ctrl+P` opens fuzzy file search — server-side, full-project, independent of expansion state.
|
|
68
70
|
|
|
69
71
|
### Skipped directories
|
|
@@ -93,6 +93,6 @@ API: `GET/PUT /api/agent-configs/:id/md/:fileType`, `GET /api/agent-configs/:id/
|
|
|
93
93
|
- **Not rendered for internal agents** (`internal: true`) — they're delegated to by other agents, never driven directly
|
|
94
94
|
|
|
95
95
|
### Internal agents
|
|
96
|
-
Agents flagged `internal: true` in agent.yaml (e.g. `__evo_agent__`, `__apply_agent__`, `__score__
|
|
96
|
+
Agents flagged `internal: true` in agent.yaml (e.g. `__evo_agent__`, `__apply_agent__`, `__score__`) are platform tooling. They are hidden from every user-facing surface: the delegation roster, `/session new` default pick, the chat agent selector, the Cron job agent picker and `halo cli`'s agent list (`halo agents`) — and have no Test button. They stay editable in the management sidebar's collapsed **Internal** group.
|
|
97
97
|
|
|
98
98
|
Replaces the old built-in test chat panel, giving a more realistic environment (full workspace tools + session persistence).
|
|
@@ -66,7 +66,7 @@ VS Code-style highlight selection (no checkboxes):
|
|
|
66
66
|
|
|
67
67
|
### Right-click menu
|
|
68
68
|
|
|
69
|
-
Items shown depend on the click target. With several items selected the menu offers only Delete; on the workspace root row only New File / New Folder / Open in Integrated Terminal / Reveal in File Manager apply:
|
|
69
|
+
Items shown depend on the click target. With several items selected the menu offers only Delete; on the workspace root row only New File / New Folder / Open in Integrated Terminal / Reveal in File Manager / Download apply:
|
|
70
70
|
|
|
71
71
|
| Action | Shown when | API / behavior |
|
|
72
72
|
|---|---|---|
|
|
@@ -74,13 +74,25 @@ Items shown depend on the click target. With several items selected the menu off
|
|
|
74
74
|
| Open in Integrated Terminal | Always | Spawns a terminal at the target dir (or file's parent) |
|
|
75
75
|
| Reveal in File Manager | Desktop app only | Opens the OS file manager (Finder / Explorer / Linux FM) at the target — a folder opens itself, a file is highlighted in its parent dir. Hidden in a plain browser (gated on the `window.haloReveal` IPC bridge exposed by the desktop preload) |
|
|
76
76
|
| Open to the Side | File or bundle directory | Splits the editor and opens the file (or bundle) in the right pane |
|
|
77
|
-
| Download | File
|
|
77
|
+
| Download | File, folder, workspace root | File: `GET /api/files/download?path=...`. Folder / root: estimate + confirm, then one streamed zip — see [Folder download](#folder-download) |
|
|
78
78
|
| Rename | Single file/folder | `POST /api/files/rename` |
|
|
79
79
|
| Delete | Single or multi-select | `DELETE /api/files?path=...` (with confirm) |
|
|
80
80
|
| Open as Workspace | Folder only | Switches the active workspace to that folder, reusing the path-input switch flow (validate → persist → reload). Shown at the bottom of the menu |
|
|
81
81
|
|
|
82
82
|
The menu auto-clamps to the viewport, so right-clicking near the window edge does not clip the bottom items.
|
|
83
83
|
|
|
84
|
+
### Folder download
|
|
85
|
+
Download on a folder (or the workspace root) zips it on the server while it streams — nothing is staged on disk or in memory (`GET /api/files/download-folder`, see [dev/api.md](../dev/api.md#files)).
|
|
86
|
+
- Clicking Download first fetches an estimate (`estimate=1`, a walk without reading contents) and opens a confirm: `≈ <size> · <n> files`, what is excluded by default with counts (node_modules / .git by name, the rest as "other build/cache folders"), how many items are always excluded or skipped
|
|
87
|
+
- Checkbox "Include node_modules, .git and other build/cache folders" (`include=excluded`) re-fetches the estimate when toggled
|
|
88
|
+
- More than 200,000 files, or a scan longer than 10 s → the dialog shows the server's 413 message ("download a subfolder instead") and Download stays disabled
|
|
89
|
+
- Confirm → a plain `<a href>` download of `<folder name>.zip` (workspace root: the workspace dir name); the browser / desktop default save flow takes it from there
|
|
90
|
+
- **Excluded by default**: any folder whose name is in the file watcher's ignore list (`IGNORED_SEGMENTS`: `.git`, `node_modules`, `dist`, `.venv`, `__pycache__`, caches …)
|
|
91
|
+
- **Always excluded**, checkbox or not: the sandbox hidden host paths (`~/.halo/secrets`, `~/.ssh`, `~/.aws` … — a home dir can be a workspace), workspace runtime state (`.halo/sessions`, logs, evo, the dbs — also in a nested workspace's `.halo/`), `.halo/settings.yaml`, any `.env` / `.env.*` file, plus common credential stores (~/.kube, cloud CLI configs, shell histories)
|
|
92
|
+
- **Names a zip can't hold** (containing `\`, or a top-level `C:`-style prefix) are skipped and listed as unreadable
|
|
93
|
+
- **Symlinks**: folder links are never followed; a file link is included only when its target stays inside the workspace and is not excluded
|
|
94
|
+
- When anything was left out, the zip carries `_halo-excluded.txt` at its root: excluded paths grouped by reason (a pruned folder is listed once, not its contents; capped at 1000 per reason plus a count), including unreadable files and skipped links
|
|
95
|
+
|
|
84
96
|
### Modification indicator
|
|
85
97
|
Files with unsaved editor edits show a coloured dot in the tree (synced from `editorStore.modifiedPaths`).
|
|
86
98
|
|
|
@@ -102,7 +102,7 @@ An installed canvas extension declares its own config in its manifest: `"setting
|
|
|
102
102
|
|
|
103
103
|
### General — built-in
|
|
104
104
|
|
|
105
|
-
Declared in [packages/server/src/settings-schema.ts](../../../packages/server/src/settings-schema.ts) `generalSection()`. The server itself is the implicit declarer. Keys: `language`, `theme`, `agent.max_retries`, `server.*`, `session.*`, `compact.*`, `sandbox.*`, `logging.*`, `observability.*` (read once at boot — restart to apply), `evolution.*`, `limits.*`. All `general.*` keys are `globalOnly`: `config.ts` resolves them through `settingsValue()` against `~/.halo/secrets/settings.yaml` only, so a workspace `settings.yaml` cannot override them. Per-workspace layering applies to namespaced `params` / `secrets` (`getServerSecret(ns, key, workspaceRoot)`, `substituteSecrets`).
|
|
105
|
+
Declared in [packages/server/src/settings-schema.ts](../../../packages/server/src/settings-schema.ts) `generalSection()`. The server itself is the implicit declarer. Keys: `language`, `theme`, `agent.max_retries`, `server.*`, `session.*`, `compact.*`, `sandbox.*`, `logging.*`, `observability.*` (read once at boot — restart the server to apply; cron / evolution runs pick a change up on their next run), `evolution.*`, `limits.*`. All `general.*` keys are `globalOnly`: `config.ts` resolves them through `settingsValue()` against `~/.halo/secrets/settings.yaml` only, so a workspace `settings.yaml` cannot override them. Per-workspace layering applies to namespaced `params` / `secrets` (`getServerSecret(ns, key, workspaceRoot)`, `substituteSecrets`).
|
|
106
106
|
|
|
107
107
|
`server.trust_proxy` (boolean, default `false`, `globalOnly`): whether the brute-force rate limiter (`middleware/brute-force.ts` `getClientIp`) trusts the `x-forwarded-for` header for client IP resolution. Direct-connect deployments leave it `false` and get the socket address. Behind a reverse proxy (nginx / Cloudflare / etc.), set it to `true` so the real client IP is honored instead of the proxy's — but only when that proxy is one you control and rewrites the header itself, otherwise a client can forge XFF to dodge lockouts.
|
|
108
108
|
|
|
@@ -123,7 +123,7 @@ There is no "default provider" setting: a newly created agent's `model:` is a co
|
|
|
123
123
|
|
|
124
124
|
**Advanced fold**: on the General page, `language` and `theme` are shown in the open; every other General field is in an "Advanced" area, collapsed by default (schema flag `advanced: true`, set in `generalSection()`).
|
|
125
125
|
|
|
126
|
-
**Restart-required fields**: `agent.max_retries`, `session.max_queue_size`, `session.max_nesting_depth`, `compact.keep_messages`, `compact.max_summary_input`, `compact.max_message_slice`, `logging.level` and the four `observability.*` keys are read once at server start (object literals in `config.ts`; observability is mapped onto `OTEL_*` env by `initObservability()` at boot). They carry `restartRequired: true`; after a save or Reset of one of them the Settings page shows a notice above the section listing the saved keys and saying the Halo server must be restarted (dismissable; it stays until dismissed). Every other General key is read live.
|
|
126
|
+
**Restart-required fields**: `agent.max_retries`, `session.max_queue_size`, `session.max_nesting_depth`, `compact.keep_messages`, `compact.max_summary_input`, `compact.max_message_slice`, `logging.level` and the four `observability.*` keys are read once at server start (object literals in `config.ts`; observability is mapped onto `OTEL_*` env by `initObservability()` at boot). For observability that applies to the server's own exporter only: cron / evolution runs are `halo cli` children that don't inherit those settings-derived `OTEL_*` vars (`cleanChildEnv()` strips them), so they use a new value on their next run — as the field descriptions say. They carry `restartRequired: true`; after a save or Reset of one of them the Settings page shows a notice above the section listing the saved keys and saying the Halo server must be restarted (dismissable; it stays until dismissed). Every other General key is read live.
|
|
127
127
|
|
|
128
128
|
### Field attributes
|
|
129
129
|
|