Commit Graph
81 Commits
Author SHA1 Message Date
NightWatcher314andGitHub d66547ff46 Add web conversation outline (#534) 2026-04-27 21:19:11 +08:00
010dc41369 feat: workspace browser with --workspace-root opt-in scoping (#526)
* feat(web): add workspace browser for multi-directory navigation

Add /browse route with a folder browser that lets users navigate
filesystem directories on connected machines and launch sessions
from any folder. Supports saved workspace paths and direct path
input. The "Start Session" action pre-fills the NewSession form.

- CLI: register machine-level `list-directory` RPC handler
- Hub: add POST /machines/:id/list-directory route
- Web: add WorkspaceBrowser component with git repo detection
- Web: add /browse route with navigation from sessions sidebar
- Web: support initialDirectory/initialMachineId in NewSession

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add --workspace-root opt-in scoping for /browse and session spawn

Adds a single new flag, \`--workspace-root <path>\` (with \`~\` / \`~/foo\`
expansion), on \`hapi runner start\` and \`hapi runner start-sync\`.

When set:
- The runner reports the path in machine metadata.
- The list-directory and spawn-session RPC handlers reject paths outside
  the root, so the web UI can't escape the configured tree even if
  someone crafts a request manually.
- The /browse page in the web UI auto-opens that root, restricts the
  breadcrumb / go-up to its subtree, and shows directory entries with
  git-repo annotations.
- The /sessions/new form keeps its existing free-text directory input
  plus autocomplete + recent-paths chips, and gains a small "Browse"
  button (next to the input) that opens /browse for picking a folder.
- Reconnect-time metadata sync ensures stale records get the field
  filled in (or cleared when the flag is dropped on a later restart),
  so the hub state matches the CLI's intent.

When unset:
- Runner behaves like the legacy hapi (no scoping, no browse feature).
- /browse renders an informative state pointing at the flag instead of
  blocking the user.
- The /sessions/new form looks identical to the pre-change behavior;
  the "Browse" button is hidden.

Includes a startup banner so \`runner start-sync\` no longer looks like
it hung, and surfaces the workspace-root sync result on stdout.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(hub): preserve workspaceRoot when rehydrating machines from store

MachineCache.refreshMachine() rebuilt the metadata object from an
explicit field allowlist, so any field not in the list (including the
new workspaceRoot) was silently dropped on every read — even though it
was correctly written to the store.

Add workspaceRoot to the zod schema, the Machine interface, and the
hand-rolled projection.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(web): friendlier empty state on /sessions

When there are zero sessions the page used to be a vast blank
rectangle with just the "0 sessions in 0 projects" caption. Render a
centered empty state instead: a calendar/agenda icon, a short heading
and hint, and two buttons — "Start a session" (→ /sessions/new) and
"Browse workspace" (→ /browse).

SessionList gains an optional onBrowse prop. Router wires it on the
sessions page so the secondary button resolves; other callers can leave
it unset to hide that button.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: document --workspace-root flag in cli/README and root README

Add a short paragraph under "Runner management" in cli/README.md
explaining what \`--workspace-root\` enables (scoped /browse tree,
list/spawn enforcement, tilde expansion) and that omitting it keeps
the legacy behavior. Mention the workspace browser in the top-level
README's Features list.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: address PR #526 review feedback

Three findings from the review bot:

1. [Major] Workspace-scope check was lexical only. With workspaceRoot
   = /safe, a symlink such as /safe/out -> /etc would pass the relative-
   path test and let list-directory / spawn-happy-session reach paths
   outside the configured root. realpath the workspaceRoot at construction
   time, and resolve every incoming path through realpath (walking up to
   the nearest existing parent for spawn targets that haven't been
   created yet) before the containment check.

2. [Minor] \`hapi runner start --workspace-root\` with no value used to
   drop the flag silently and start the runner unscoped. Now treats a
   missing or flag-shaped next argument as an error.

3. [Minor] /sessions/new's "Browse" button always opened /browse using
   localStorage's last-used machine, ignoring the user's current
   selection. NewSession already passes machineId in its callback;
   forward it through the /browse search params and seed
   WorkspaceBrowser with it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(cli): gate list-directory RPC behind --workspace-root opt-in

Without a configured workspaceRoot, isWithinWorkspaceRoot() returns
true unconditionally, leaving the new list-directory RPC able to
enumerate any path on the runner. The Web UI already hides Browse
for these machines, but the backend should enforce the opt-in too.

Refuse the RPC up front when no workspace root is configured.

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 09:59:18 +08:00
weishu 97be34e21c Add Codex model selection 2026-04-25 10:48:12 +08:00
weishu 79a13d26c6 Fix Codex reasoning effort resume and updates 2026-04-10 11:50:03 +08:00
450b4f8aa7 fix(web): reconnect SSE immediately when tab becomes visible (#398)
* fix(web): reconnect SSE immediately when tab becomes visible

The SSE watchdog skips heartbeat checks while the tab is hidden. If the
connection dies in the background, the user sees stale messages after
switching back and has to wait up to 10 s for the next watchdog tick.

Add a visibilitychange listener that checks heartbeat staleness
immediately when the tab becomes visible and reconnects if stale.

via [HAPI](https://hapi.run)

Co-Authored-By: HAPI <noreply@hapi.run>

* fix(web): map visibility-recovery reason in reconnecting banner

The new 'visibility-recovery' reconnect reason was not mapped in
getReasonLabel(), so the raw string would appear in the UI banner.
Add localized labels for both en and zh-CN.

via [HAPI](https://hapi.run)

Co-Authored-By: HAPI <noreply@hapi.run>

---------

Co-authored-by: HAPI <noreply@hapi.run>
2026-04-05 13:21:19 +08:00
QihanandGitHub 92885ddef0 fix(web): hide unsupported Codex slash commands in remote mode (#357) 2026-03-25 05:38:25 +08:00
a200fe9628 feat(claude): add effort setting parity with model across stack (#353)
Co-authored-by: Xiaoyi <xiaoyizhang@microsoft.com>
2026-03-24 21:15:48 +08:00
lifu963andGitHub 895654ddf6 fix(terminal): prevent infinite reconnect loop on Windows hosts (#336) 2026-03-21 21:45:40 +08:00
dotblueandGitHub ea45797b6f web: add terminal font size setting (#324) 2026-03-20 08:43:36 +08:00
ROOOOandGitHub eb18530fed fix(web): warn before creating missing session directories (#317) 2026-03-19 15:11:54 +08:00
ROOOOandGitHub cb09f0b898 feat: add codex reasoning effort option (#297) 2026-03-17 22:55:55 +08:00
weishu 16829b7c78 Add support for codex plan mode 2026-03-16 20:48:39 +08:00
weishu 329d28a93c remove , using instead 2026-03-16 18:29:09 +08:00
weishu 02c8e12e80 unify model selection 2026-03-16 18:29:09 +08:00
METOandGitHub a0c35bc225 feat(web): add appearance setting (follow system / dark / light) (#253)
* feat(web): add appearance setting (follow system / dark / light)

Add user-facing appearance preference to the settings page, allowing
users to choose between Follow System, Dark, and Light themes. The
preference is persisted to localStorage and takes priority over
automatic detection in the existing theme pipeline.

* fix(web): update theme on cross-tab appearance change

The storage event handler only updated React state without calling
updateScheme(), leaving data-theme and useTheme subscribers stale.

* fix(web): move cross-tab appearance sync to global initializeTheme

The storage event listener was inside useAppearance(), which is only
mounted on the settings page. Other pages never received cross-tab
theme updates. Move the listener into initializeTheme() so all pages
respond to appearance changes from other tabs.
2026-03-08 10:47:53 +08:00
METOandGitHub 446649576c fix(web): use i18n translation for hardcoded "Create Session" strings (#259)
Replace hardcoded English strings with translation function calls
in SpawnSession.tsx and router.tsx. Add newSession.title key for
the NewSessionPage header to match the newSession.* namespace.
2026-03-07 14:49:57 +08:00
LihengwannaflyandGitHub 1942f088ff fix(sync): add SSE heartbeat and alive status (#223) 2026-02-28 01:46:21 +08:00
gaius-codiusandGitHub 77cfa715f9 fix(web): harden clipboard copy and terminal paste flows (#187) 2026-02-19 08:08:52 +08:00
weishu cc9b9279bd fix(web): require hub URL without clearing input 2026-02-06 17:03:46 +08:00
weishu 5b27f6b41e feat(web): Add reconnecting feedback when SSE connection is lost (#125)
- Add ReconnectingBanner component to show "Reconnecting..." status
- Track SSE connection state in App.tsx with onDisconnect handler
- Add onBlocked callback to useSendMessage for handling blocked send attempts
- Provide haptic feedback when send is blocked due to no API or session
- Show toast notification when message cannot be sent due to server disconnection
- Add translation keys for reconnecting message and send blocked feedback in en/zh-CN

close #125
2026-02-01 19:40:43 +08:00
Trustin LeeandGitHub 7cad11ca27 Add About section to settings page with version info and tests (#119)
* feat(web): add About section to settings page

- Add website link to hapi.run
- Display app version from CLI package
- Display protocol version from shared module
- Add Vitest testing setup with settings page tests

🤖 Generated with Claude Code

* test(web): add tests for website link and i18n key usage

Address residual risks mentioned in PR review:
- Test website link URL and security attributes (target, rel)
- Verify correct i18n keys are used for About section via spy

Simplify test setup by using real I18nProvider and en locale.

🤖 Generated with Claude Code
2026-01-30 09:48:49 +08:00
therainismeandweishu efbe4f8d90 feat(web): add font size setting
- Add Settings > Display > Font Size selector (80/90/100/110/120%)
- Persist preference (hapi-font-scale) and apply globally via --app-font-scale
- Normalize main UI typography to match Settings
2026-01-29 16:25:47 +08:00
weishu 37e10a831b feat: rename server package to hub
Rename the `server/` directory to `hub/` and update all references
across CLI, docs, web, and workspace configuration.
2026-01-27 19:51:21 +08:00
weishu ae9650ca7c feat: add support for Codex's request_user_input tool
Implement full support for the request_user_input tool with both Web UI and CLI
components. This includes:

- New view and footer components for request_user_input tool UI
- Tool registration in knownTools and view registries
- Nested answer format support (Record<string, { answers: string[] }>)
- Backward compatibility with flat answer format (Record<string, string[]>)
- Permission handler updates for CLI request_user_input acceptance
- Type definitions and schema updates across shared/cli/server/web packages
- Translation strings for request_user_input UI elements
- Conditional footer rendering in ToolCard for question tools
2026-01-26 11:58:36 +08:00
weishu e130dfd24b feat: add model selection for AI agents (claude, codex, gemini)
Add a new ModelSelector component that allows users to choose specific model variants for different AI agents. This includes:
- ModelSelector UI component with agent-specific model options
- Model parameter propagation through API, RPC, and spawning layers
- Support for auto model selection (default behavior)
- Localization strings for English and Chinese
- Type definitions for model options per agent
2026-01-23 11:55:29 +08:00
weishu 15d550d39a feat: add voice language selection in settings
Add support for users to select voice language preference, which is passed through to ElevenLabs agents via platform settings overrides. Includes new language mapping utilities, UI controls in settings page, and updated voice session initialization.
2026-01-20 00:57:01 +08:00
weishu 7a5946731d feat: add settings page with language dropdown 2026-01-19 21:33:22 +08:00
weishu a928e82db2 Add error hint 2026-01-19 19:03:01 +08:00
weishu 8f5b773b23 feat: voice assistant 2026-01-19 18:16:57 +08:00
weishu 53e4de6684 feat: add file upload support 2026-01-17 19:38:12 +08:00
ChenandGitHub aaaad33e61 feat: add i18n support and enhance session UI (#50) 2026-01-10 22:07:22 +08:00