@turmind/halo 1.6.4 → 1.6.6
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 +18 -9
- package/admin-out/404.html +1 -1
- package/admin-out/_next/static/chunks/87-6a2716c98a819c4e.js +1 -0
- package/admin-out/_next/static/chunks/989-066a874961bd519f.js +1 -0
- package/admin-out/_next/static/chunks/app/page-812bcbb46db628b6.js +1 -0
- package/admin-out/_next/static/css/e890aa0d13e94290.css +1 -0
- package/admin-out/index.html +1 -1
- package/admin-out/index.txt +5 -5
- package/bundled-docs/design/a2a.md +1 -1
- package/bundled-docs/design/canvas-extensions.md +38 -7
- package/bundled-docs/design/cron.md +13 -5
- package/bundled-docs/design/feishu.md +2 -0
- package/bundled-docs/design/halo-city.md +18 -149
- package/bundled-docs/design/slack.md +2 -2
- package/bundled-docs/design/storage.md +6 -2
- package/bundled-docs/design/stt-local.md +106 -0
- package/bundled-docs/design/web.md +1 -1
- package/bundled-docs/design/wecom.md +1 -1
- package/bundled-docs/dev/add-model-provider.md +1 -1
- package/bundled-docs/dev/api.md +13 -10
- package/bundled-docs/dev/desktop-packaging.md +37 -9
- package/bundled-docs/dev/env.md +1 -1
- package/bundled-docs/requirements/chat.md +8 -0
- package/bundled-docs/requirements/workspace.md +4 -0
- package/dist/index.js +1509 -604
- package/package.json +2 -1
- package/templates/models/mimo-token-plan-china.yaml +3 -55
- package/templates/skills/cron/SKILL.md +2 -1
- package/templates/skills/cron/manage-cron.py +2 -1
- package/admin-out/_next/static/chunks/147-d4200c70445aabb6.js +0 -1
- package/admin-out/_next/static/chunks/989-5d7743ff56d00dd7.js +0 -1
- package/admin-out/_next/static/chunks/app/page-8881b4f87a3d5ae8.js +0 -1
- package/admin-out/_next/static/css/3b4dcd0ac6b8eae8.css +0 -1
- /package/admin-out/_next/static/{kfp1cMc36J6hjZ06L9mm- → Yc05ORrVk5IE9P1Gd8Ojh}/_buildManifest.js +0 -0
- /package/admin-out/_next/static/{kfp1cMc36J6hjZ06L9mm- → Yc05ORrVk5IE9P1Gd8Ojh}/_ssgManifest.js +0 -0
|
@@ -104,8 +104,8 @@ HALO_STAGE_FULL=1 CI=true pnpm dist:win
|
|
|
104
104
|
```
|
|
105
105
|
|
|
106
106
|
`HALO_STAGE_FULL=1` is **mandatory** here: a cross-stage must re-run the
|
|
107
|
-
per-target native fixups (`@parcel/watcher-win32-x64` swap, `
|
|
108
|
-
win prebuild), which the fast path skips. `wine` must be installed (electron-
|
|
107
|
+
per-target native fixups (`@parcel/watcher-win32-x64` swap, `sherpa-onnx-win-x64`
|
|
108
|
+
swap, `better-sqlite3` win prebuild), which the fast path skips. `wine` must be installed (electron-
|
|
109
109
|
builder runs the nsis maker through it).
|
|
110
110
|
|
|
111
111
|
Verified on the v0.1.9 build (Linux x86_64 host → win-x64):
|
|
@@ -114,7 +114,9 @@ Verified on the v0.1.9 build (Linux x86_64 host → win-x64):
|
|
|
114
114
|
<ver>.exe` + `.exe.blockmap` + `win-unpacked/`. The "discard the stray
|
|
115
115
|
arm64 dmg" gotcha below is mac-host-only.
|
|
116
116
|
- **Native arch check** — every staged `.node` must be PE32+ x86-64, no ELF:
|
|
117
|
-
`find dist/win-unpacked -path '*watcher-*' -name '*.node' | xargs file
|
|
117
|
+
`find dist/win-unpacked -path '*watcher-*' -name '*.node' | xargs file`,
|
|
118
|
+
`find dist/win-unpacked -path '*sherpa-onnx-*' \( -name '*.node' -o -name '*.dll' \) | xargs file`
|
|
119
|
+
(only `sherpa-onnx-win-x64` dirs, one per runtime, no `linux-x64`) and
|
|
118
120
|
`file dist/win-unpacked/resources/node.exe` (should read `PE32+ ... x86-64`).
|
|
119
121
|
- **Two benign warnings**, both expected: `file source doesn't exist
|
|
120
122
|
from=.../resources/node` (win bundles `node.exe`, not the Unix `node` — the
|
|
@@ -204,7 +206,9 @@ Still good practice: build server + admin **before** `pnpm dist:arm64`.
|
|
|
204
206
|
3. **Native fixup** — re-fetch `better-sqlite3` prebuilds via `prebuild-install
|
|
205
207
|
--target=$NODE_VERSION_BARE` **unconditionally** (pins the ABI to the bundled
|
|
206
208
|
node regardless of the build host's node — see the ABI gotcha below);
|
|
207
|
-
`@parcel/watcher`'s per-platform binary is swapped only when cross-staging
|
|
209
|
+
`@parcel/watcher`'s per-platform binary is swapped only when cross-staging;
|
|
210
|
+
`sherpa-onnx`'s per-platform package is swapped to the target on every full
|
|
211
|
+
stage (server-runtime and cli-runtime — see the sherpa gotcha below).
|
|
208
212
|
4. **Trim bloat** — drop non-target `node-pty` prebuilds, `better-sqlite3`'s
|
|
209
213
|
C source, and the server's `src/`/`tests/`.
|
|
210
214
|
5. **Copy `admin-out/`** — the Next.js static export.
|
|
@@ -212,9 +216,10 @@ Still good practice: build server + admin **before** `pnpm dist:arm64`.
|
|
|
212
216
|
nodejs.org, extract the `node` binary into `resources/`.
|
|
213
217
|
7. **codesign (ad-hoc)** — `codesign --force --sign -` on the node binary for
|
|
214
218
|
Gatekeeper. **We deliberately do NOT `strip`** — see gotcha below.
|
|
215
|
-
8. **Native-addon smoke test** — load the staged better-sqlite3
|
|
216
|
-
bundled node binary; abort the build if
|
|
217
|
-
runs on full and fast paths). See the
|
|
219
|
+
8. **Native-addon smoke test** — load the staged better-sqlite3 and
|
|
220
|
+
sherpa-onnx with the bundled node binary; abort the build if either can't
|
|
221
|
+
`dlopen` (runs on full and fast paths, skipped when cross-staging). See the
|
|
222
|
+
ABI gotcha below.
|
|
218
223
|
|
|
219
224
|
## Gotchas (learned the hard way)
|
|
220
225
|
|
|
@@ -456,8 +461,8 @@ Still good practice: build server + admin **before** `pnpm dist:arm64`.
|
|
|
456
461
|
`node_modules` differs from what's on disk, run with `HALO_STAGE_FULL=1`. The
|
|
457
462
|
fast path only re-syncs compiled outputs and **reuses the existing
|
|
458
463
|
`node_modules`**, so it never re-runs the per-target native fixups
|
|
459
|
-
(`@parcel/watcher`
|
|
460
|
-
forgetting: the win/x64 dmg still carries the host's arm64 binaries.
|
|
464
|
+
(`@parcel/watcher` / `sherpa-onnx` swaps, `better-sqlite3` prebuild-install).
|
|
465
|
+
Symptom of forgetting: the win/x64 dmg still carries the host's arm64 binaries.
|
|
461
466
|
|
|
462
467
|
- **`@parcel/watcher` binary doesn't cross-stage via `npm install`.** Its
|
|
463
468
|
per-platform binary package (`@parcel/watcher-win32-x64` etc.) declares
|
|
@@ -474,6 +479,29 @@ Still good practice: build server + admin **before** `pnpm dist:arm64`.
|
|
|
474
479
|
(`better-sqlite3` and `node-pty` don't hit this — they use `prebuild-install`
|
|
475
480
|
and bundled multi-platform prebuilds respectively.)
|
|
476
481
|
|
|
482
|
+
- **`sherpa-onnx-node` (local STT) has the same os/cpu trap — and its Windows
|
|
483
|
+
package is `win-x64`, not `win32-x64`.** The main package is pure JS; the
|
|
484
|
+
N-API addon + onnxruntime libs ship in `sherpa-onnx-<plat>-<arch>` optional
|
|
485
|
+
deps (`darwin-arm64`, `win-x64`, `linux-x64`, …), and npm / pnpm install only
|
|
486
|
+
the host's, so a Linux → win stage ends up with just `sherpa-onnx-linux-x64`.
|
|
487
|
+
`installSherpaBinary()` `npm pack`s the target's package at the exact
|
|
488
|
+
installed `sherpa-onnx-node` version, extracts it as a sibling of
|
|
489
|
+
`sherpa-onnx-node` (its loader requires `../sherpa-onnx-<plat>-<arch>/sherpa-onnx.node`)
|
|
490
|
+
in both server-runtime and cli-runtime, and deletes every other platform's
|
|
491
|
+
package. Runs on every full stage, cross or not. The server loads it
|
|
492
|
+
lazily (`await import`), so a broken binary never blocks boot — it only
|
|
493
|
+
surfaces as dead transcription; on a native stage `smokeTestNativeAddons()`
|
|
494
|
+
`require`s it with the bundled node to catch that early.
|
|
495
|
+
- **Windows: must be loaded by a process named `node.exe`.** The win
|
|
496
|
+
`sherpa-onnx.node` delay-loads `node.exe` for its N-API imports, so
|
|
497
|
+
`require`-ing it inside `Halo.exe` (Electron main / `ELECTRON_RUN_AS_NODE`)
|
|
498
|
+
fails. Fine today: the server and the `halo.cmd` CLI both run under the
|
|
499
|
+
bundled `resources\node.exe`. Keep it out of the Electron process.
|
|
500
|
+
- **macOS: minimum OS for the arm64 `.node` is 14.0 (`LC_BUILD_VERSION`
|
|
501
|
+
minos; the dylibs say 11.0), unverified on older macOS.** Whether 12/13 can
|
|
502
|
+
load it hasn't been tested on real hardware. Dylibs resolve through
|
|
503
|
+
`@loader_path` rpath, so no `DYLD_LIBRARY_PATH` is needed.
|
|
504
|
+
|
|
477
505
|
- **`ENOTEMPTY` / `directory not empty` mid-stage or in electron-builder.** A
|
|
478
506
|
prior stage's `resources/{cli,server}-runtime/node_modules` (or
|
|
479
507
|
`dist/win-unpacked`) can fail to delete cleanly on macOS (open handles, deep
|
package/bundled-docs/dev/env.md
CHANGED
|
@@ -99,7 +99,7 @@ Source: `packages/server/src/config.ts`
|
|
|
99
99
|
|---|---|---|---|
|
|
100
100
|
| `HALO_PORT` | `9527` | `config.yaml server.port` | Hono listen port |
|
|
101
101
|
| `HALO_PASSWORD` | (none) | `config.yaml server.password` (scrypt hash) | Plaintext login password. When set, takes precedence over the stored hash and bypasses scrypt entirely — intended for Docker / systemd / CI. It also satisfies the **startup gate**: the server refuses to boot with no password configured, and env plaintext counts as a first-class credential there, so an env-only deployment (`halo setup -y && HALO_PASSWORD=... halo server start`, no stored hash) boots fine. The hash is set by `halo setup` for interactive installs. |
|
|
102
|
-
| `HALO_CORS_ORIGINS` | empty (reflect any origin) | `config.yaml server.cors_origins` | CORS allowlist (comma-separated, exact origins). Empty = reflect any incoming Origin **without** `Allow-Credentials` (header-token callers like `x-token` work; cookie-carrying cross-origin requests don't). A non-empty list = only those origins get CORS, with `Allow-Credentials` (e.g. a frontend behind an SSO that must send its cookie). Read at startup — a change needs a restart. Prefer a same-origin reverse proxy over listing origins (see
|
|
102
|
+
| `HALO_CORS_ORIGINS` | empty (reflect any origin) | `config.yaml server.cors_origins` | CORS allowlist (comma-separated, exact origins). Empty = reflect any incoming Origin **without** `Allow-Credentials` (header-token callers like `x-token` work; cookie-carrying cross-origin requests don't). A non-empty list = only those origins get CORS, with `Allow-Credentials` (e.g. a frontend behind an SSO that must send its cookie). Read at startup — a change needs a restart. Prefer a same-origin reverse proxy over listing origins (see the halo-city extension's [README](https://github.com/turmind/halo-hub/blob/main/extensions/halo-city/README.md#和-halo-同源)). |
|
|
103
103
|
| `HALO_FRONTEND_DIR` | auto (bundled `admin-out`, else `packages/admin/out`) | — | Static frontend dir; resolved against the current working directory |
|
|
104
104
|
| `HALO_MAX_CONTEXT_TOKENS` | `272000` | — | Model max context |
|
|
105
105
|
| `HALO_SHELL_TIMEOUT` | `120000` | `config.yaml timeout.shell_exec` | Shell command timeout (ms) |
|
|
@@ -144,6 +144,14 @@ Constraints:
|
|
|
144
144
|
- Desktop: screen share needs macOS **Screen Recording** permission; the camera prompts for **Camera** permission on first use, with an "Open Settings" path if previously denied. Browser: the page must be served over HTTPS or from localhost (`getDisplayMedia` / `getUserMedia` are absent elsewhere, so the buttons don't render); a denied camera shows a hint pointing at the address bar's site settings.
|
|
145
145
|
- Binding is **in-memory only** and shared by all chat tabs — a page reload or restart requires re-selecting.
|
|
146
146
|
|
|
147
|
+
### Extension buttons (chat bar)
|
|
148
|
+
An installed extension whose manifest declares `chatbar` (e.g. the hub's voice input) adds one button to the input toolbar, right after the capture buttons; several sort by `chatbar.order`, then id. No such extension installed = toolbar unchanged; install / uninstall shows up without a reload.
|
|
149
|
+
- **Button**: 32×32 like Attach; the extension's icon in the toolbar colour (a microphone when it has none); tooltip = its title (Chinese UI: `title_zh` → `title` → name; English: `title` → name). Primary-coloured while its panel is open.
|
|
150
|
+
- **Panel**: opens above the whole input box, floating over the editor if the chat is docked low (up to 420 px wide, nearly full width on a phone; height from the manifest, default 160 px, shrunk to fit the space above the input — never so far that its title bar and × leave the screen) with a thin title bar and ×. It follows the input when the dock is resized or the floating chat is moved; switching chat tabs, or hiding the chat (terminal tab, collapsed dock), closes it. One panel at a time — another extension's button switches to it. Its own button again, ×, or Esc closes it (Esc in the text box closes the panel first, before the usual "Esc interrupts the turn"). Clicking elsewhere does **not** close it, so the user can keep dictating while editing the draft.
|
|
151
|
+
- **Lifetime**: the extension runs only while its panel is open; closing stops it (the microphone with it). An extension that says it is still busy (e.g. the last sentence is being recognised) gets to finish first: on its button / × / Esc the panel stays (button still lit, text still arriving) until it is done — at most 35 s; closing it again closes it at once. Switching chat tabs, hiding the chat, or opening another extension's panel closes it at once. Uninstalling it while open closes the panel. An extension that doesn't answer within 10 s shows "did not respond" with Retry.
|
|
152
|
+
- **Text into the draft**: the extension can insert text at the cursor (replacing a selection), exactly as given; the cursor lands after it and keyboard focus stays in the panel. It works while the agent is replying (it only edits the draft). The extension can **never send** — the user always presses Send.
|
|
153
|
+
- Settings → Extensions labels such an extension "Chat bar". Design: [design/canvas-extensions.md → Chat-bar entries](../design/canvas-extensions.md#chat-bar-entries).
|
|
154
|
+
|
|
147
155
|
### The agent's face (`self.html`)
|
|
148
156
|
A second channel beyond text: a visual space the agent drives in real time to express itself. Works everywhere (pure HTML/canvas, no Electron dependency) — desktop **and** plain browser.
|
|
149
157
|
|
|
@@ -42,6 +42,10 @@ The Bottom Panel (Chat + Terminal) can also be **floated** into a draggable wind
|
|
|
42
42
|
|
|
43
43
|
The Source Control entry is hidden in workspaces that are not git repos.
|
|
44
44
|
|
|
45
|
+
**Extension entries.** An installed [canvas extension](../design/canvas-extensions.md#activity-bar-entries) whose manifest declares `activity` adds one button after Cron (several sort by the manifest's `order`, then id; the built-in tabs never move). It uses the extension's icon (tinted like the built-in icons; a puzzle piece when it has none) and its title / description in the hover drawer, in the admin's language. Clicking it shows the extension's page full-width in the main area with no sidebar, like Agents / Settings; leaving the tab closes the page (anything it was playing or refreshing stops). The last-used page is restored after a reload; if that extension has been removed, or doesn't run on this device, the workspace opens on Explorer instead. With no such extension installed, the bar is unchanged.
|
|
46
|
+
|
|
47
|
+
**Short windows.** When the window is too short for every view button, the upper group (built-in views + extension entries) scrolls (no visible scrollbar); Settings and the quick-toggles entry stay pinned at the bottom.
|
|
48
|
+
|
|
45
49
|
Below Settings sits the quick-toggles entry (network status, finish notification, and on desktop pin / keep-screen-awake) — see [explorer.md → Desktop windows](explorer.md#desktop-windows-multi-window).
|
|
46
50
|
|
|
47
51
|
### Hover drawer
|