Commit Graph
562 Commits
Author SHA1 Message Date
f970072f66 fix(hub): add PATCH to CORS allowMethods so session rename works (#391)
The rename endpoint uses PATCH /api/sessions/:id, but the CORS
middleware only allowed GET, POST, DELETE, OPTIONS. Browsers send a
preflight OPTIONS request for PATCH; without it in allowMethods the
preflight fails and the request never reaches the handler, causing
"Failed to rename" in the web UI every time.

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

Co-authored-by: HAPI <noreply@hapi.run>
2026-04-05 12:32:53 +08:00
DengQiandGitHub 139a21c66f feat(web): add copy button to assistant messages (#392) 2026-04-05 12:32:36 +08:00
Junmo KimandGitHub 00ba610ab0 feat: display rate limit warnings instead of raw JSON (#388)
* refactor(web): extract normalizeTimestamp helper in presentation

Extract the shared seconds-vs-milliseconds normalization logic into
a private `normalizeTimestamp()` helper. No behavior change —
`formatUnixTimestamp()` produces identical output.

* refactor(web): return AgentEvent from parseClaudeUsageLimit

Change return type from `number | null` to `AgentEvent | null` so
the caller doesn't need to construct the event object. No behavior
change — the same `limit-reached` event is produced.

* feat(cli): convert rate_limit_event to standardized text format

Parse undocumented Claude `rate_limit_event` JSON in the CLI adapter
layer (AcpMessageHandler) before it reaches the web.

Converted text format (pipe-delimited):
  - "Claude AI usage limit warning|{ts}|{pct}|{rateLimitType}"
  - "Claude AI usage limit reached|{ts}|{rateLimitType}"

Status handling:
  - `allowed_warning` → warning text with utilization and limit type
  - `rejected` → reached text with limit type
  - `allowed` → silently suppressed (noise)
  - unknown statuses → passed through as-is (forward-compatible)

* feat(web): display rate limit warnings with limit type

Parse standardized pipe-delimited text from the CLI adapter into
`limit-warning` and `limit-reached` events, displaying the rate
limit type (5-hour, 7-day) when available.

- `limit-warning`: "⚠️ Usage limit 90% (5-hour) · resets 2:00 PM"
- `limit-reached`: " Usage limit reached (5-hour) until 4/2/2026"
- Backward compatible: `limit-reached` without limitType still works

The `reached` regex uses `(?:\|([^|]*))?$` to optionally match the
limitType field, maintaining compatibility with the existing format.

* refactor(cli): move rate limit parsing out of flushText

Remove rate limit detection from flushText() back to plain buffer
flush. The next commit will re-add parsing at the chunk level
(handleUpdate) where it can intercept before buffer merging.

Includes failing tests that demonstrate the mixed-chunk bug:
when a rate_limit_event chunk arrives in the same turn as normal
text, the JSON leaks into the merged buffer.

* fix(cli): intercept rate_limit_event at chunk level, not flush

Move rate limit detection from flushText() to the agentMessageChunk
handler so it fires before the chunk enters the shared text buffer.

Previously, a rate_limit_event chunk arriving in the same turn as
normal text would merge into bufferedText and leak as raw JSON.
Now the chunk is intercepted individually, the existing buffer is
flushed first (preserving prior text), and the converted message
is emitted separately.

* fix(cli): skip flush when suppressing allowed rate_limit_event

Only flush the text buffer when the parsed event will actually be
displayed. Suppressed events (e.g. status: 'allowed') now return
immediately without flushing, preventing a text → allowed → text
sequence from splitting one answer into two agent-text blocks.

* fix(web): include limitType in limit-reached reconcile key

Without this, reprocessing a message from the old format (no
limitType) to the new typed format reuses the stale block and
the (5-hour)/(7-day) suffix never appears.
2026-04-03 08:25:22 +08:00
Haoqing WangandGitHub 36022a0a1a fix(web): filter system-injected XML tags from rendering as raw text (#387)
* fix(web): filter system-injected XML tags from rendering as raw text

Claude Code injects internal messages (<task-notification>, <system-reminder>,
<command-name>, <local-command-caveat>) as user-role messages. The web UI was
rendering these as raw XML text visible to users.

- Parse <task-notification> and display as agent-event with summary text
- Silently drop <system-reminder>, <command-name>, <local-command-caveat>
- Add tests covering all injection prefixes and edge cases

* fix(web): scope system injection filtering to Claude sessions only

Address review feedback: the XML tag filtering was applied at the
generic timeline layer, which could incorrectly hide legitimate user
messages in Codex/Gemini sessions.

- Add isClaudeSession flag threaded from Session.metadata.claudeSessionId
- Only filter system-injected tags when isClaudeSession is true
- Add tests verifying non-Claude sessions pass through all messages

* fix(web): treat all string user output as sidechain to prevent prompt leaks

Restores the fix from 3cf96ab that was accidentally reverted in 2205e04.

In normalizeUserOutput(), string-content user messages arriving through
the agent output path are never real user input (real user text goes
through normalizeUserRecord). Previously, non-sidechain string messages
were emitted as role:'user', causing subagent prompts and system-injected
messages to render as user text in the web UI.

Now all string-content user messages in this path are:
- <task-notification> with summary → converted to role:'event'
- Everything else → marked as sidechain (matched to parent Task tool
  call by the tracer, or harmlessly skipped by the reducer)

This provides a root-level fix that prevents ANY string user message
from the agent output path from leaking as visible user text.

* ci: retrigger CI

* fix(web): remove superseded return-null filter from upstream PR #372

The upstream `return null` filter for <task-notification> and
<system-reminder> (from PR #372) is now superseded by the comprehensive
sidechain upgrade logic. Remove it to avoid short-circuiting the new
task-notification → event conversion.

* refactor(web): remove reducer-side system injection filtering

System-injected messages are now fully handled in normalizeUserOutput()
(normalize layer), so the redundant filtering in reduceTimeline() is no
longer needed. Removing it also eliminates the risk of accidentally
hiding legitimate user messages that happen to start with XML tags.

- Remove SYSTEM_INJECTION_PREFIXES, isSystemInjectedMessage,
  parseTaskNotificationSummary from reducerTimeline.ts
- Remove isClaudeSession plumbing from reducer.ts and SessionChat.tsx
- Simplify reducerTimeline.test.ts to only test pass-through behavior
2026-04-02 14:08:03 +08:00
gaius-codiusandGitHub 845a1001fe feat(web): group sessions by machine and improve group headers (#383) 2026-04-01 18:30:31 +08:00
Junmo KimandGitHub 4eb88c5d7e feat(gemini): support mid-session model change (#379) 2026-04-01 11:15:11 +08:00
weishu fa0ce1ca94 Release version 0.16.5 2026-03-31 18:53:38 +08:00
weishu 4248540fb4 auto approve in yolo mode for codex 2026-03-31 18:51:34 +08:00
weishu ca7cb9ac90 auto approve title tool for codex 2026-03-31 18:36:31 +08:00
Haoqing WangandGitHub 2c20b04bec fix(web): suppress Task tool prompt text from leaking into chat (#372) 2026-03-31 10:46:42 +08:00
Junmo KimandGitHub 3a073dc4a9 fix(gemini): wire --resume flag through to Gemini backend (#378) 2026-03-31 10:46:21 +08:00
Wong ChihungandGitHub 1f67d36c06 feat(models): support new gemini models and codex gpt-5.4-mini (#376) 2026-03-29 21:33:33 +08:00
weishuandGitHub 11644ef9e0 Update SECURITY.md 2026-03-29 09:47:17 +08:00
weishuandGitHub 22d5a62409 Create SECURITY.md for security policy
Add a security policy document outlining supported versions and vulnerability reporting.
2026-03-28 21:36:54 +08:00
Haoqing WangandGitHub 2216f98c58 fix(web): render multiline mutation results as code blocks to prevent markdown mis-parsing (#371) 2026-03-27 16:05:10 +08:00
godot42xandGitHub cbd1f78d2d fix: 修复Windows下路径解析导致mkdir权限错误 (#369) 2026-03-27 05:32:51 +08:00
xyzhang626andGitHub 63337873c3 fix(claude): handle async background task notifications in remote mode (#354) 2026-03-26 08:07:06 +08:00
Haoqing WangandGitHub 279f75815e fix(cli): prevent system-injected messages from appearing as user role (#361) 2026-03-26 08:06:30 +08:00
QihanandGitHub 2b133feec5 fix(web): keep mobile views scrollable and new-session actions reachable (#364) 2026-03-26 08:04:58 +08:00
QihanandGitHub 92885ddef0 fix(web): hide unsupported Codex slash commands in remote mode (#357) 2026-03-25 05:38:25 +08:00
QihanandGitHub acda983e02 fix(web): restore mobile scrolling outside Telegram (#358) 2026-03-25 05:37:48 +08:00
Haoqing WangandGitHub 6384697b03 fix(cli): filter isMeta and isCompactSummary messages in local and remote mode (#359) 2026-03-25 05:36:41 +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
Haoqing WangandGitHub 30265fdc25 fix(cli): filter invisible system messages in local mode (#351) 2026-03-24 19:21:17 +08:00
Haoqing WangandGitHub 24834fbef4 fix(hub): handle Telegram bot polling errors instead of silently swallowing them (#350) 2026-03-24 17:56:50 +08:00
ad4df369ea feat(web): add copy button to user messages (#349)
* feat(web): add copy button to user messages

Add a small copy button to user message bubbles for easy text copying,
especially useful on mobile where selecting text is difficult.

- Mobile: button always visible (opacity-60)
- Desktop: button appears on hover
- Uses existing useCopyToClipboard hook with haptic feedback
- Conditionally rendered to avoid empty container spacing

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

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

* fix(web): use valid CSS property in copy button transition

transition-[opacity,colors] is invalid because 'colors' is not a CSS
property (only Tailwind's utility class 'transition-colors' expands it).
Use 'background-color' instead so the hover background transition
actually works.

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

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

---------

Co-authored-by: HAPI <noreply@hapi.run>
2026-03-24 14:16:19 +08:00
weishu 7da6f7c5c5 Release version 0.16.4 2026-03-24 13:04:42 +08:00
weishu 900ee2eccb fix PWA icon 2026-03-24 12:32:37 +08:00
weishu 304789620b Fix reason effort setting not working. close #346, close #333 2026-03-24 12:04:52 +08:00
Haoqing WangandGitHub b802092bf7 fix(cli): treat any exit code as expected when abort was requested (#347) 2026-03-24 02:41:13 +08:00
Haoqing WangandGitHub 9de5bed19f fix(web): add visual indicator for sending message status (#344) 2026-03-23 14:57:10 +08:00
Haoqing WangandGitHub 8eea49f9da fix(cli): fix process exit handling deadlock and error masking in Claude SDK (#343) 2026-03-23 14:56:45 +08:00
Haoqing WangandGitHub 4c11fbe5f2 fix(web): stop rendering sidechain prompt as user message (#340) 2026-03-23 12:40:03 +08:00
dotblueandGitHub bcc2558dff feat: Render question text and options with markdown (#339) 2026-03-23 05:02:52 +08:00
xyzhang626andGitHub b6ecdc7b44 fix(hub): pass resumeSessionId when resuming session (#337) 2026-03-22 06:49:14 +08:00
lifu963andGitHub 895654ddf6 fix(terminal): prevent infinite reconnect loop on Windows hosts (#336) 2026-03-21 21:45:40 +08:00
pppobearandGitHub ae39fc5e77 Fix Codex default approval policy for remote sessions (#328) 2026-03-20 18:45:18 +08:00
weishu a02f908dc5 fix test 2026-03-20 13:19:10 +08:00
weishu 32f05d99a0 Release version 0.16.3 2026-03-20 12:17:35 +08:00
weishu 9742522ee8 rm tg 2026-03-20 12:15:24 +08:00
pppobearandGitHub f539f10507 fix(web): fix push notification click 404 on GitHub Pages (#322) 2026-03-20 08:46:21 +08:00
Junmo KimandGitHub d76b1a6ac0 refactor: introduce model-agnostic agent interfaces (#323) 2026-03-20 08:45:32 +08:00
dotblueandGitHub ea45797b6f web: add terminal font size setting (#324) 2026-03-20 08:43:36 +08:00
2e2727835e fix(web): restore scrolling on new session page (#318)
Co-authored-by: liyang <liyang25@pku.edu.cn>
2026-03-19 22:32:45 +08:00
ROOOOandGitHub 397ef35f5c fix(cli): preserve requested cwd for runner-spawned sessions (#315) 2026-03-19 15:15:41 +08:00
ROOOOandGitHub 987010f447 fix(codex): pass session cwd to app-server (#316) 2026-03-19 15:12:11 +08:00
ROOOOandGitHub eb18530fed fix(web): warn before creating missing session directories (#317) 2026-03-19 15:11:54 +08:00
DengQiandweishu ecc7236692 fix(web): improve UI performance on Windows with long conversations (#311) 2026-03-18 19:11:36 +08:00
ROOOOandGitHub f967bd9928 fix(runner): restart when hub identity changes (#303)
* fix(runner): restart when hub identity changes

* fix(runner): fail closed on missing identity
2026-03-18 10:43:36 +08:00
2ecd56dbe8 fix(gemini): notify hub when session is aborted (#307) (#308)
Co-authored-by: Junmo Kim <me@junmo.kim>
2026-03-18 08:12:57 +08:00