@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/README.md
CHANGED
|
@@ -8,25 +8,43 @@
|
|
|
8
8
|
|
|
9
9
|
**Throw in an idea. A team of agents builds it.**
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
A self-hosted AI agent team that works in your project folder. Bring your own model key and drive it from a browser, Slack, Telegram or the terminal. A primary agent breaks the work down and fans it out to sub-agents that run in parallel; every tool call shows up live, and you can interrupt, redirect or take over at any point. Everything the team knows and produces is plain files in the workspace — no hidden memory, no opaque state.
|
|
12
12
|
|
|
13
13
|

|
|
14
14
|
<p align="center"><sub>One prompt — <i>“Build a landing page for our coffee roastery… split the sections across sub-agents in parallel, then assemble.”</i> Executors fan out, report back, and the assembled page previews in Canvas, all in one browser tab.</sub></p>
|
|
15
15
|
|
|
16
16
|
## Install
|
|
17
17
|
|
|
18
|
+
Halo runs on Linux (x64 / arm64), macOS and Windows, and needs **Node.js 22+**. Ubuntu 24.04's own `nodejs` package is 18 and won't work (`halo` refuses to start on it), so get 22 first:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - && sudo apt-get install -y nodejs # Ubuntu / Debian
|
|
22
|
+
brew install node@22 # macOS (keg-only: add it to PATH as brew prints)
|
|
23
|
+
nvm install 22 # with nvm (or: fnm install 22)
|
|
24
|
+
```
|
|
25
|
+
|
|
18
26
|
```bash
|
|
19
27
|
npm install -g @turmind/halo # one binary, all subcommands
|
|
20
28
|
halo setup # interactive: password / port / model keys / optional skills
|
|
21
29
|
halo server start # → open http://localhost:9527
|
|
22
30
|
```
|
|
23
31
|
|
|
24
|
-
Bring any one model key — Anthropic, OpenAI (or any OpenAI-compatible endpoint), DeepSeek, Kimi, Qwen…
|
|
32
|
+
Bring any one model key — Anthropic, OpenAI (or any OpenAI-compatible endpoint), DeepSeek, Kimi, Qwen… An AWS account is **not** required; Bedrock is just one of the [providers](#models) (and can use your AWS credential chain instead of a key).
|
|
33
|
+
|
|
34
|
+
- **`sudo`**: with a system-wide Node (apt / NodeSource), `npm install -g` needs `sudo`; with nvm / fnm it doesn't.
|
|
35
|
+
- **In `halo setup`**: at *Configure model provider keys now?* pick **Configure…** (the default). Pick your provider and paste the key, choose **── Done** (the last row; ↑ wraps to it), then press Enter on *Switch default agent to …*.
|
|
36
|
+
- **On a remote box**: run `halo server start -d` (plain `start` stays in the foreground and dies with your SSH session), tunnel with `ssh -L 9527:localhost:9527 user@host`, and open `http://localhost:9527` on your machine. Don't open 9527 in a security group — see [Status & Limitations](#status--limitations).
|
|
37
|
+
- **Linux sandbox**: the `workspace` / `readonly` access levels need `sudo apt install bubblewrap`, and on Ubuntu 23.10+ / 24.04 also an [AppArmor profile](.halo/docs/dev/deploy.md#bubblewrap-on-ubuntu-2310-and-2404-apparmor). Without it `/api/health` shows `sandbox: null` and non-full sessions can't run shell.
|
|
38
|
+
- **Upgrade**: `halo upgrade && halo server restart`, or under systemd `halo upgrade && sudo systemctl restart halo` ([deploy.md Option C](.halo/docs/dev/deploy.md#option-c-systemd-for-the-npm-install)). Bundled docs, agents and skills refresh on the next start.
|
|
39
|
+
- **Docker / CI**: `halo setup --non-interactive`. `HALO_PASSWORD` is the *admin* password only; `HALO_DEFAULT_PROVIDER=<provider>` binds the built-in agents without a prompt. Model keys go in `~/.halo/secrets/settings.yaml`, e.g. `api_key: "<<DEEPSEEK_API_KEY>>"` under `deepseek.secrets` with `DEEPSEEK_API_KEY` set at runtime ([env.md](.halo/docs/dev/env.md)).
|
|
40
|
+
- **From source**: `pnpm install && pnpm build` (pnpm 11).
|
|
25
41
|
|
|
26
|
-
|
|
42
|
+
**Desktop app**: [GitHub releases](https://github.com/turmind/halo-agent/releases) carry a Windows x64 `.exe` and a macOS Apple Silicon `.dmg` (not every release has both) that bundle the server, admin and their own Node runtime — no `npm`, same `~/.halo/` data, so you can switch later. They're unsigned (macOS "damaged" → `sudo xattr -dr com.apple.quarantine /Applications/Halo.app`; Windows SmartScreen may warn).
|
|
27
43
|
|
|
28
44
|
> [!IMPORTANT]
|
|
29
|
-
> **First message fails with `Could not load credentials from any providers`?** The built-in
|
|
45
|
+
> **First message fails with `Could not load credentials from any providers`?** The built-in agents ship pointing at AWS Bedrock, and the *"Bind the default agent to a provider you just configured?"* step in `halo setup` was skipped. Re-run `halo setup` — it rebinds every built-in agent, the internal `/evo` ones included — or switch the model provider under **Agents → default**.
|
|
46
|
+
>
|
|
47
|
+
> **On EC2 / ECS with an instance role there is no error**: an unbound install quietly uses Bedrock Claude on that AWS account instead. Check which model answers in the footer of `halo cli -v "hi"`, or under **Agents → default**.
|
|
30
48
|
|
|
31
49
|
## Why Halo
|
|
32
50
|
|
|
@@ -52,11 +70,11 @@ my-project/
|
|
|
52
70
|
└─ src/ … # your actual project
|
|
53
71
|
```
|
|
54
72
|
|
|
55
|
-
|
|
73
|
+
Commit `.halo/` with your code and whoever clones it gets the same agents, skills and knowledge — the real files, not an export (they bring their own model key); `/workspace share` zips the config without sessions, memory or secrets. Initializing the repo from Halo's Source Control panel writes a `.gitignore` for sessions, logs, `tmp/` and databases; in an existing repo, add those yourself, and keep real keys out of `.halo/settings.yaml` (use `<<ENV>>` placeholders).
|
|
56
74
|
|
|
57
75
|
### 🌐 One workspace, every screen
|
|
58
76
|
|
|
59
|
-
Kick off a build in the browser, check progress from WeChat on the metro, drop a follow-up in Telegram or Slack, finish in the terminal. Every channel connects to the *same* workspace
|
|
77
|
+
Kick off a build in the browser, check progress from WeChat on the metro, drop a follow-up in Telegram or Slack, finish in the terminal. Every channel connects to the *same* workspace — channels are doors, the workspace is the room — and a full-access account can `/session switch` to pick up a conversation started elsewhere.
|
|
60
78
|
|
|
61
79
|
<p align="center">
|
|
62
80
|
<img src="assets/wechat-phone.jpg" alt="Halo in WeChat" width="270" />
|
|
@@ -67,71 +85,32 @@ Kick off a build in the browser, check progress from WeChat on the metro, drop a
|
|
|
67
85
|
|
|
68
86
|
### 👁 Watch it think
|
|
69
87
|
|
|
70
|
-
|
|
88
|
+
The primary agent's reasoning, every tool call (sub-agents' included) and every file change stream in real time; a sub-agent's full log opens from the **Sessions** tab. Interrupts are graceful (conversation repair, not a hard kill), and sub-agents report back when done. You stay in the loop instead of running and praying.
|
|
71
89
|
|
|
72
90
|

|
|
73
91
|
<p align="center"><sub>The primary agent fans out three executors in parallel — every <code>start_session</code> and tool call visible as it happens.</sub></p>
|
|
74
92
|
|
|
75
|
-
And when you'd rather have ambience than logs: [Halo City](#halo-city) renders the same runtime as a living pixel town.
|
|
76
|
-
|
|
77
93
|
## Also in the box
|
|
78
94
|
|
|
79
|
-
- **
|
|
80
|
-
- **IDE-grade admin** — chat + Monaco editor + file explorer + git panel + terminal (xterm.js) in one browser tab.
|
|
81
|
-
- **Skills** —
|
|
95
|
+
- **Per-agent models** — each agent picks its own provider and model: Claude on Bedrock for the heavy lifting, a cheap model for routine sub-tasks. No code changes.
|
|
96
|
+
- **IDE-grade admin** — chat + Monaco editor + file explorer + git panel + terminal (xterm.js) in one browser tab, in four themes.
|
|
97
|
+
- **Skills and agents are files** — a skill is markdown injected on demand; an agent is a persona plus an `agent.yaml`. Workspace-scoped or global, no code required.
|
|
98
|
+
- **Preview extensions** — installable viewers and small apps for the editor: 3D models, draw.io, Excalidraw, Jupyter notebooks, a meeting recorder and more from [halo-hub](https://github.com/turmind/halo-hub). Install with `/extension install <id>` or a zip under **Settings → Extensions** ([design](.halo/docs/design/canvas-extensions.md)).
|
|
82
99
|
- **Cron tasks** — scheduled agent runs (recurring or one-shot) whose output fans out to your chat channels.
|
|
83
|
-
- **
|
|
84
|
-
- **ACP adapter** — plug a halo workspace into Claude Code as a native ACP agent, or let one halo delegate to another.
|
|
100
|
+
- **Access levels** — `full` / `workspace` / `readonly` per session, enforced by an OS sandbox (bubblewrap on Linux, Seatbelt on macOS); a sub-agent never gets more access than its parent ([how levels are set](.halo/docs/guide/delegation-and-access.md#5-access-levels), [limits](#status--limitations)).
|
|
85
101
|
- **Structured sessions** — hierarchical parent ↔ child sessions with async coordination and auto-reports on completion.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
- ☁️ **AgentCore runtime mode** — run Halo as an Amazon Bedrock AgentCore Runtime (A2A protocol) with `halo agentcore`, on an EFS-backed workspace.
|
|
90
|
-
- 🎨 **Four UI themes** — dark, light, midnight, warm; synced server-side so every browser gets your pick.
|
|
91
|
-
- ⌨️ **TUI overhaul** — reworked input, verbose mode, and persistent history in the standalone terminal client.
|
|
92
|
-
- ✂️ **Graceful interrupts, fully surfaced** — interrupted tool calls are repaired and shown in the session UI instead of vanishing.
|
|
93
|
-
|
|
94
|
-

|
|
95
|
-
|
|
96
|
-
## Quick Start
|
|
97
|
-
|
|
98
|
-
Published on npm as [`@turmind/halo`](https://www.npmjs.com/package/@turmind/halo) — one binary, all subcommands. After the three install commands above, open **http://localhost:9527**.
|
|
99
|
-
|
|
100
|
-
| Prerequisite | Notes |
|
|
101
|
-
|---|---|
|
|
102
|
-
| Node.js >= 22 | the only hard system requirement |
|
|
103
|
-
| An API key for any supported model provider | entered during `halo setup`; AWS Bedrock users can leave keys unset and use the standard credential chain (env / `~/.aws` / instance role) instead |
|
|
104
|
-
| pnpm >= 9 | source builds only |
|
|
105
|
-
|
|
106
|
-
- **Bind your provider to the agent**: agents choose providers, and the built-in `default` agent ships pointing at AWS Bedrock. When you configure a different provider, `halo setup` ends by offering to rebind the built-in agents to it (with a single provider and no Bedrock keys, Enter accepts). Skipped it? Re-run `halo setup`, or switch once in **Agents → default → model provider**.
|
|
107
|
-
- **Upgrade**: `halo upgrade && halo server restart`. The startup check refreshes bundled docs / agents / skills automatically when the on-disk template version is behind.
|
|
108
|
-
- **Docker / CI**: `halo setup --non-interactive` and supply credentials via the `HALO_PASSWORD` env var; `HALO_DEFAULT_PROVIDER=<provider>` binds the built-in agents without a prompt.
|
|
109
|
-
- **From source**: `pnpm install && pnpm build`.
|
|
110
|
-
|
|
111
|
-
### Talk to it from curl
|
|
112
|
-
|
|
113
|
-
Every workspace can expose a token-authenticated HTTP + SSE endpoint — the Web channel, aka the "build your own UI" channel:
|
|
114
|
-
|
|
115
|
-
1. In the admin, open **Channels → Web → Add Account**, pick a workspace and access level, and copy the token (shown once).
|
|
116
|
-
2. Stream a conversation:
|
|
117
|
-
|
|
118
|
-
```bash
|
|
119
|
-
curl -N -H "x-token: $TOKEN" -H "Content-Type: application/json" \
|
|
120
|
-
-d '{"message":"What files are in this workspace?"}' \
|
|
121
|
-
http://localhost:9527/api/web/chat
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
The response is SSE frames — `session` / `thinking` / `tool_call` / `stream` / `complete` — full protocol in [`.halo/docs/guide/channels/web.md`](.halo/docs/guide/channels/web.md).
|
|
102
|
+
- **Beyond one workspace** — [relay](.halo/docs/design/relay.md) work to another workspace on the same server, talk [A2A v1.0](.halo/docs/design/a2a.md) with other agent servers, or run headless as an Amazon Bedrock [AgentCore](.halo/docs/design/agentcore.md) Runtime with `halo agentcore`.
|
|
103
|
+
- **Observability** — set one OTLP endpoint and traces, metrics and logs (GenAI semantic conventions) go to any OpenTelemetry collector; `/api/metrics` serves Prometheus gauges ([design](.halo/docs/design/observability.md)).
|
|
125
104
|
|
|
126
105
|
## Models
|
|
127
106
|
|
|
128
|
-
Configured per-agent through one provider-agnostic runtime. AWS Bedrock Claude is the primary target; the rest are first-class.
|
|
107
|
+
Configured per-agent through one provider-agnostic runtime. AWS Bedrock Claude is the primary target; the rest are first-class. `/extension models` pulls updated provider configs from the hub without a Halo release.
|
|
129
108
|
|
|
130
109
|
| Provider | Notes |
|
|
131
110
|
|---|---|
|
|
132
111
|
| **AWS Bedrock Claude** | Primary — Bedrock Invoke API |
|
|
133
112
|
| AWS Bedrock Mantle | OpenAI GPT-class models via Bedrock |
|
|
134
|
-
| AWS Bedrock OpenAI-compatible | GPT
|
|
113
|
+
| AWS Bedrock OpenAI-compatible | GPT, Grok, Kimi and GLM models via the bedrock-runtime OpenAI Responses API |
|
|
135
114
|
| Anthropic | Direct API |
|
|
136
115
|
| OpenAI | Direct / any OpenAI-compatible endpoint |
|
|
137
116
|
| DeepSeek | |
|
|
@@ -142,12 +121,13 @@ Configured per-agent through one provider-agnostic runtime. AWS Bedrock Claude i
|
|
|
142
121
|
| Hunyuan (Tencent) | |
|
|
143
122
|
| Doubao (Volcengine) | |
|
|
144
123
|
| Zhipu AI (GLM) | GLM-5.3 family; vision on the Flash models |
|
|
124
|
+
| Google Gemini | Gemini API (OpenAI-compatible endpoint) — 3.8 Flash, 3.5 Flash-Lite |
|
|
145
125
|
|
|
146
126
|

|
|
147
127
|
|
|
148
128
|
## Channels
|
|
149
129
|
|
|
150
|
-
|
|
130
|
+
Telegram, Slack, Feishu, WeCom and WeChat all connect outbound — no public URL or open port needed. New channel accounts start at `readonly`; each [onboarding guide](.halo/docs/guide/channels/) says who can reach the bot.
|
|
151
131
|
|
|
152
132
|
| Channel | Transport | Notes |
|
|
153
133
|
|---|---|---|
|
|
@@ -159,51 +139,62 @@ Every channel shares the same workspace and session state. Onboarding guides liv
|
|
|
159
139
|
| **Feishu / Lark** | Long-connect | `appId` + `appSecret` |
|
|
160
140
|
| **WeCom** | Long-connect | `botId` + `secret` (智能机器人, no HTTP send API) |
|
|
161
141
|
| **WeChat** | QR bind | Scan to bind, mobile access |
|
|
162
|
-
| **ACP adapter** | stdio JSON-RPC |
|
|
142
|
+
| **ACP adapter** | stdio JSON-RPC | `halo acp` bridges ACP editors (Zed, JetBrains IDEs) onto the Web channel — [guide](.halo/docs/guide/channels/acp.md) |
|
|
163
143
|
|
|
164
144
|

|
|
165
145
|
<p align="center"><sub>The TUI runs the same agent loop in your terminal — here delegating to an executor and consolidating its report, no server needed.</sub></p>
|
|
166
146
|
|
|
147
|
+
### Talk to it from curl
|
|
148
|
+
|
|
149
|
+
The Web channel is a token-authenticated HTTP + SSE endpoint for your own UI or scripts. In the admin, open **Channels → Web → Add Account**, pick a workspace and access level, and copy the token (shown once). Then:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
curl -N -H "x-token: $TOKEN" -H "Content-Type: application/json" \
|
|
153
|
+
-d '{"message":"What files are in this workspace?"}' \
|
|
154
|
+
http://localhost:9527/api/web/chat
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
The response is SSE frames — `session` / `thinking` / `tool_call` / `stream` / `complete` — full protocol in [`.halo/docs/guide/channels/web.md`](.halo/docs/guide/channels/web.md).
|
|
158
|
+
|
|
167
159
|
## Halo City
|
|
168
160
|
|
|
169
|
-
A read-only pixel city that visualizes a live halo server: each workspace is a building, each session an animal citizen — at a desk when working, grabbing coffee or hitting the arcade when idle. Click any citizen to inspect the real thing: live session log, delegation chain, last tool call, token usage. Pure client-side canvas on a single polling endpoint — **zero model tokens burned**.
|
|
161
|
+
A read-only pixel city that visualizes a live halo server: each workspace is a building, each session an animal citizen — at a desk when working, grabbing coffee or hitting the arcade when idle. Click any citizen to inspect the real thing: live session log, delegation chain, last tool call, token usage. Pure client-side canvas on a single polling endpoint — **zero model tokens burned**. Plain static files in [`halo-city/`](halo-city/), no build — see the [design notes](.halo/docs/design/halo-city.md).
|
|
170
162
|
|
|
171
163
|

|
|
172
164
|
<p align="center"><sub>Street level: three sub-agent citizens heads-down in the <code>aurora-cafe</code> building; the inspector shows one executor's live log and delegation chain.</sub></p>
|
|
173
165
|
|
|
174
|
-
Lives at [`halo-city/`](halo-city/) (plain static files, no build) — see the [design notes](.halo/docs/design/halo-city.md).
|
|
175
|
-
|
|
176
166
|
## Tech Stack
|
|
177
167
|
|
|
178
168
|
- **Monorepo**: pnpm workspace (`core`, `server`, `admin`, `cli`, `desktop`, `acp-adapter`)
|
|
179
|
-
- **Backend**: Hono + WebSocket, single Node.js process on port 9527
|
|
169
|
+
- **Backend**: Hono + WebSocket, single Node.js 22+ process on port 9527 (ESM, TypeScript strict)
|
|
180
170
|
- **Frontend**: Next.js 15 static export, served directly by Hono
|
|
181
171
|
- **Agent**: custom orchestration loop, provider-agnostic `ModelRuntime` interface
|
|
182
172
|
- **Storage**: SQLite + Drizzle ORM — no external services to stand up
|
|
183
|
-
- **Runtime**: Node.js 22+, ESM, TypeScript strict
|
|
184
173
|
|
|
185
174
|
## Docs
|
|
186
175
|
|
|
187
176
|
- [`.halo/INDEX.md`](.halo/INDEX.md) — project overview + doc index
|
|
177
|
+
- [`.halo/docs/guide/`](.halo/docs/guide/README.md) — user guide
|
|
188
178
|
- [`.halo/docs/requirements/overview.md`](.halo/docs/requirements/overview.md) — product concept
|
|
189
179
|
- [`.halo/docs/design/architecture.md`](.halo/docs/design/architecture.md) — backend architecture
|
|
190
180
|
- [`.halo/docs/design/evolution.md`](.halo/docs/design/evolution.md) — self-evolution design
|
|
191
181
|
- [`.halo/docs/guide/channels/`](.halo/docs/guide/channels/) — per-channel onboarding guides
|
|
192
182
|
- [`.halo/docs/dev/deploy.md`](.halo/docs/dev/deploy.md) — deployment (systemd / Nginx)
|
|
193
183
|
- [`.halo/docs/dev/env.md`](.halo/docs/dev/env.md) — env vars, build commands
|
|
184
|
+
- [`CHANGELOG.md`](CHANGELOG.md) — what changed in each release
|
|
194
185
|
- [`CLAUDE.md`](CLAUDE.md) — development instructions for Claude Code
|
|
195
186
|
|
|
196
187
|
## Status & Limitations
|
|
197
188
|
|
|
198
189
|
Halo is young — treat it as an early-stage project:
|
|
199
190
|
|
|
200
|
-
- **
|
|
201
|
-
- **
|
|
202
|
-
- **
|
|
203
|
-
- **
|
|
191
|
+
- **The sandbox guards writes and credentials, not the network.** In `workspace` / `readonly` sessions, bubblewrap (Linux) or Seatbelt (macOS) limits writes to the workspace and temp dirs (`readonly`: temp dirs only) and hides `~/.halo/secrets`, `~/.ssh`, `~/.aws` and similar paths; the rest of the host stays readable and outbound connections work. The threat model is accidental damage and path escape by a trusted agent — not containing a malicious skill or extension, or a prompt-injected session sending out what it can read.
|
|
192
|
+
- **Windows hosts have no sandbox.** There a `workspace` session is effectively `full`, and `readonly` can read any path the halo process can — don't hand out non-`full` channel tokens on a Windows host expecting isolation ([dev/tools.md](.halo/docs/dev/tools.md)).
|
|
193
|
+
- **The admin is single-tenant, on plain HTTP, on all interfaces.** One password (5 failed logins lock that IP out for 15 minutes); whoever holds the admin cookie controls the server — every workspace, shell as the server user, every channel credential. Keep port 9527 behind a firewall, VPN or SSH tunnel, or a reverse proxy with TLS ([deploy.md §10](.halo/docs/dev/deploy.md#10-optional-nginx-reverse-proxy)), and give other people channel accounts with their own access levels instead of the admin login.
|
|
194
|
+
- **Tests are unit/regression-level.** CI runs them on every push and PR to `main`; there's no end-to-end or integration suite yet.
|
|
204
195
|
- **APIs and on-disk formats may still change between versions.** Expect rough edges while things stabilize.
|
|
205
196
|
|
|
206
|
-
If you hit something broken or surprising, please open an issue — early feedback is genuinely useful right now.
|
|
197
|
+
If you hit something broken or surprising, please open an issue — early feedback is genuinely useful right now. Security reports go through [SECURITY.md](SECURITY.md).
|
|
207
198
|
|
|
208
199
|
## Contributing
|
|
209
200
|
|
package/admin-out/404.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><!--
|
|
1
|
+
<!DOCTYPE html><!--kfp1cMc36J6hjZ06L9mm_--><html lang="en" class="dark"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" href="/_next/static/media/e4af272ccee01ff0-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="stylesheet" href="/_next/static/css/7b736202f0b1dbfd.css" data-precedence="next"/><link rel="stylesheet" href="/_next/static/css/3b4dcd0ac6b8eae8.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-74f577c1b094f942.js"/><script src="/_next/static/chunks/1b86ba38-c29611e086b2ce25.js" async=""></script><script src="/_next/static/chunks/698-19872069fed27164.js" async=""></script><script src="/_next/static/chunks/main-app-340a5b58ed229c4d.js" async=""></script><script src="/_next/static/chunks/989-5d7743ff56d00dd7.js" async=""></script><script src="/_next/static/chunks/app/layout-ea161287d934ba96.js" async=""></script><meta name="robots" content="noindex"/><meta name="next-size-adjust" content=""/><title>404: This page could not be found.</title><title>Halo - Multi-Agent Workspace</title><meta name="description" content="Multi-agent collaboration workspace for complex project delivery"/><link rel="icon" href="/favicon.ico" type="image/x-icon" sizes="16x16"/><link rel="icon" href="/icon.svg?3a6863548daca964" type="image/svg+xml" sizes="any"/><script>try{var t=localStorage.getItem('halo_theme');if(t==='light'||t==='midnight'||t==='warm')document.documentElement.dataset.theme=t}catch(e){}</script><script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body class="__variable_d8ebd1 font-sans antialiased"><div hidden=""><!--$--><!--/$--></div><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/webpack-74f577c1b094f942.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[58321,[\"989\",\"static/chunks/989-5d7743ff56d00dd7.js\",\"177\",\"static/chunks/app/layout-ea161287d934ba96.js\"],\"ThemeProvider\"]\n3:I[24554,[\"989\",\"static/chunks/989-5d7743ff56d00dd7.js\",\"177\",\"static/chunks/app/layout-ea161287d934ba96.js\"],\"AppI18nProvider\"]\n4:I[63693,[],\"\"]\n5:I[74713,[],\"\"]\n6:I[23632,[],\"OutletBoundary\"]\n8:I[86889,[],\"AsyncMetadataOutlet\"]\na:I[23632,[],\"ViewportBoundary\"]\nc:I[23632,[],\"MetadataBoundary\"]\nd:\"$Sreact.suspense\"\nf:I[1935,[],\"\"]\n:HL[\"/_next/static/media/e4af272ccee01ff0-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/css/7b736202f0b1dbfd.css\",\"style\"]\n:HL[\"/_next/static/css/3b4dcd0ac6b8eae8.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"kfp1cMc36J6hjZ06L9mm-\",\"p\":\"\",\"c\":[\"\",\"_not-found\"],\"i\":false,\"f\":[[[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],[\"\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/7b736202f0b1dbfd.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"link\",\"1\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/3b4dcd0ac6b8eae8.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"className\":\"dark\",\"suppressHydrationWarning\":true,\"children\":[[\"$\",\"head\",null,{\"children\":[\"$\",\"script\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"try{var t=localStorage.getItem('halo_theme');if(t==='light'||t==='midnight'||t==='warm')document.documentElement.dataset.theme=t}catch(e){}\"}}]}],[\"$\",\"body\",null,{\"className\":\"__variable_d8ebd1 font-sans antialiased\",\"children\":[\"$\",\"$L2\",null,{\"children\":[\"$\",\"$L3\",null,{\"children\":[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]}]}]]}]]}],{\"children\":[\"/_not-found\",[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[\"__PAGE__\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],null,[\"$\",\"$L6\",null,{\"children\":[\"$L7\",[\"$\",\"$L8\",null,{\"promise\":\"$@9\"}]]}]]}],{},null,false]},null,false]},null,false],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[[\"$\",\"$La\",null,{\"children\":\"$Lb\"}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]],[\"$\",\"$Lc\",null,{\"children\":[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$d\",null,{\"fallback\":null,\"children\":\"$Le\"}]}]}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$f\",[]],\"s\":false,\"S\":true}\n"])</script><script>self.__next_f.push([1,"b:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n7:null\n"])</script><script>self.__next_f.push([1,"10:I[88809,[],\"IconMark\"]\n9:{\"metadata\":[[\"$\",\"title\",\"0\",{\"children\":\"Halo - Multi-Agent Workspace\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Multi-agent collaboration workspace for complex project delivery\"}],[\"$\",\"link\",\"2\",{\"rel\":\"icon\",\"href\":\"/favicon.ico\",\"type\":\"image/x-icon\",\"sizes\":\"16x16\"}],[\"$\",\"link\",\"3\",{\"rel\":\"icon\",\"href\":\"/icon.svg?3a6863548daca964\",\"type\":\"image/svg+xml\",\"sizes\":\"any\"}],[\"$\",\"$L10\",\"4\",{}]],\"error\":null,\"digest\":\"$undefined\"}\n"])</script><script>self.__next_f.push([1,"e:\"$9:metadata\"\n"])</script></body></html>
|