4828 Commits

Author SHA1 Message Date
m4 fb13457f6f feat: consolidate desktop and provider updates
CI / Supply-chain scan (push) Has been cancelled
Docker Build, Test, and Publish / Detect affected areas (push) Has been cancelled
auto-fix lint issues & formatting / Generate eslint --fix patch (push) Has been cancelled
Nix flake check / Detect affected areas (push) Has been cancelled
Deploy Site / deploy-vercel (push) Has been cancelled
Deploy Site / deploy-docs (push) Has been cancelled
CI / Detect affected areas (push) Has been cancelled
Docker Build, Test, and Publish / build (amd64, type=gha,scope=docker-amd64, type=gha,mode=max,scope=docker-amd64, linux/amd64, ubuntu-latest-32-core) (push) Has been cancelled
CI / Desktop E2E (push) Has been cancelled
CI / Docs Site (push) Has been cancelled
CI / Deny unrelated histories (push) Has been cancelled
CI / Check contributors (push) Has been cancelled
Docker Build, Test, and Publish / build (arm64, type=gha,scope=docker-arm64, type=gha,mode=max,scope=docker-arm64, linux/arm64, ubuntu-latest-32-arm-core) (push) Has been cancelled
CI / Check uv.lock (push) Has been cancelled
CI / Check no committed infographics (push) Has been cancelled
CI / Profile artifact check (push) Has been cancelled
Docker Build, Test, and Publish / publish (amd64, type=gha,scope=docker-amd64, type=gha,mode=max,scope=docker-amd64, linux/amd64, ubuntu-latest-32-core) (push) Has been cancelled
Docker Build, Test, and Publish / publish (arm64, type=gha,scope=docker-arm64, type=gha,mode=max,scope=docker-arm64, linux/arm64, ubuntu-latest-32-arm-core) (push) Has been cancelled
Docker Build, Test, and Publish / merge (push) Has been cancelled
auto-fix lint issues & formatting / Apply patch (push) Has been cancelled
CI / Check no case-colliding filenames (push) Has been cancelled
CI / package-lock.json diff (push) Has been cancelled
CI / Lint Docker scripts (push) Has been cancelled
CI / Review label gate (push) Has been cancelled
CI / All required checks pass (push) Has been cancelled
CI / CI timing report (push) Has been cancelled
CI / Python tests (push) Has been cancelled
CI / OS-specific tests (push) Has been cancelled
CI / Python lints (push) Has been cancelled
CI / JS & TS checks (push) Has been cancelled
CI / Installer tests (push) Has been cancelled
CI / Rust tests (push) Has been cancelled
Nix flake check / nix flake check (push) Has been cancelled
2026-09-27 17:37:19 +08:00
m4 226350cd04 feat(desktop): open workspace files with system app 2026-09-27 17:32:11 +08:00
m4 3272102fe9 feat(desktop): 登录记住用户名密码 + 用户名不可改(2026-09-20 用户裁定)
记住凭据:登录成功自动把 {site, email, password} 存进 safeStorage 独立槽
(复刻 freemodel2api remembered 模式),登录页启动预填;登出不清,
U-6 解绑全清时一并抹掉。renderer 只有读口(rememberedLoad)。

用户名不可改:/me 资料页 username 从可编辑表单降为只读展示行,
可改字段只剩 nickname/phone。

测试:electron 侧 login 自动存/登出保留/换号覆盖/解绑抹除;renderer 侧
预填、读取失败兜底、username 只读。聚焦 59 passed;全量 10408 passed,
仅 4 个既有失败(clean HEAD 同现,与本次无关)。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-09-20 17:39:12 +08:00
m4 5832cbbe9c fix(desktop): DB-T6 recordBind 收窄改写——TS 6.0.3 对布尔判别式真值收窄不生效
改显式 === 比较;门禁补 tsconfig.electron.json(根 tsconfig 不覆盖 electron/)。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-09-19 22:59:55 +08:00
m4 10a46a00a9 feat(desktop): DB-T6 登录后自动绑定 + 机器码/pending 可查 + 失败可见(§21 U-7)
登录成功/恢复会话后 main 自动发起免口令绑定(每进程一次),复用 U-1
通路,失败绝不阻塞登录;binding-status 扩展机器码(插件 GET status)
与 pending/失败码回查;/me 绑定区单源展示 + 重试,侧栏卡片 amber 角标。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-09-19 22:50:04 +08:00
m4 55868dc7b1 feat(desktop): DB-T4c/T5 /me 绑定区 UI + token 脱敏静态断言(§21 U-1/U-6)
- /me 新增机器绑定区:未绑定一键免口令绑定,binding_pending 展示确认码,
  已绑定显示 site+installationId,解绑走破坏性确认框(U-6 全清语义写明)
- i18n binding 18 键 × 六语言
- DB-T5:user-account-hygiene 测试行级 grep——日志/诊断行零 token,
  preload 桥不回传 token 字段
2026-09-19 18:12:55 +08:00
m4 a45c35ce54 feat(desktop): DB-T4b 绑定/解绑 IPC + U-6 全清(§21 U-1/U-5/U-6)
- binding-status:只读插件 state.json 非敏感二字段,state 损坏 fail-closed
- bind-machine:session_token 免口令绑定(U-1),401 接入 refresh-retry 链,
  binding_pending 透传确认码;email/password 不出 main
- unbind-machine:尽力服务端撤销 → 插件 purge → 删所有会话;purge 失败
  结构化返回且不动本地会话(不留半清假象);登出≠解绑硬断言
2026-09-19 18:00:34 +08:00
m4 9d606be4f1 feat(desktop): DB-T3 侧栏用户卡 + /me 资料页(§21 U-4)
- 侧栏底部用户卡:U-4 展示名 + 邮箱,离线 amber 圆点,点击进 /me
- /me 资料页(ROUTES_AREA workspace 页):三字段白名单编辑
  (username/nickname/phone,只提交改动项),离线缓存数据时间横幅,
  登出入口(登出≠解绑 U-1)
- electron:PATCH /api/v2/me 客户端 + update-profile IPC(email 等
  非白名单键一律丢弃;响应四字段合并进完整快照,不覆盖 plan 等)
- i18n userAccount.me 20 键 × 6 语言;electron +3 / ui +8 测试全绿

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-09-19 13:35:00 +08:00
m4 357ac45281 feat(desktop): DB-T2 强制登录门 + 注册/找回 + U-5 机器-用户锁(§21)
- 登录门:非 signed_in 全屏盖 app,登录/注册/找回三页,只盖 UI
  不断机器通道(U-1);status 通道异常落登录页不砖(U-3)
- U-5:登录成功当场校验本机 installation ∈ 会话用户列表,不符即
  销毁会话并提示绑定者邮箱;绑定状态损坏 fail-closed
- relay 客户端补注册/找回四通道 + installations/binding-owner 查询;
  IPC 预期失败全部结构化 {ok:false, code} 返回
- i18n userAccount 48 键 × 6 语言;electron +11 / ui +7 测试全绿

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-09-19 13:12:49 +08:00
m4 a48a81a5f0 feat(desktop): DB-T1 用户账号会话层(§21 U-1/U-3)
relay /auth/* 客户端 + safeStorage 落盘 + IPC 边界:token 只活 main
进程;401 反应式刷新,refresh 被拒为唯一硬终点(本地清零 +
sessionExpired);relay 不可达标离线并回缓存 profile + 数据时间。
登出≠解绑,机器绑定不经此层。

tests: +19(electron 15 / ui 4);typecheck 绿;electron/ui 全量仅
既有环境性失败(干净树同败,已对照)。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-09-19 12:42:31 +08:00
m4 05be76016a feat(desktop): workspace bar carries the full path as the breadcrumb
auto-fix lint issues & formatting / Generate eslint --fix patch (push) Has been cancelled
Nix flake check / Detect affected areas (push) Has been cancelled
CI / Detect affected areas (push) Has been cancelled
Docker Build, Test, and Publish / Detect affected areas (push) Has been cancelled
CI / JS & TS checks (push) Has been cancelled
CI / Installer tests (push) Has been cancelled
CI / Rust tests (push) Has been cancelled
CI / Desktop E2E (push) Has been cancelled
CI / Docs Site (push) Has been cancelled
CI / Deny unrelated histories (push) Has been cancelled
CI / Check contributors (push) Has been cancelled
CI / Check uv.lock (push) Has been cancelled
CI / Check no committed infographics (push) Has been cancelled
CI / Profile artifact check (push) Has been cancelled
CI / Check no case-colliding filenames (push) Has been cancelled
CI / package-lock.json diff (push) Has been cancelled
CI / Lint Docker scripts (push) Has been cancelled
CI / Supply-chain scan (push) Has been cancelled
CI / Review label gate (push) Has been cancelled
Docker Build, Test, and Publish / merge (push) Has been cancelled
auto-fix lint issues & formatting / Apply patch (push) Has been cancelled
CI / Python tests (push) Has been cancelled
CI / OS-specific tests (push) Has been cancelled
CI / Python lints (push) Has been cancelled
CI / All required checks pass (push) Has been cancelled
CI / CI timing report (push) Has been cancelled
Docker Build, Test, and Publish / build (amd64, type=gha,scope=docker-amd64, type=gha,mode=max,scope=docker-amd64, linux/amd64, ubuntu-latest-32-core) (push) Has been cancelled
Docker Build, Test, and Publish / build (arm64, type=gha,scope=docker-arm64, type=gha,mode=max,scope=docker-arm64, linux/arm64, ubuntu-latest-32-arm-core) (push) Has been cancelled
Docker Build, Test, and Publish / publish (amd64, type=gha,scope=docker-amd64, type=gha,mode=max,scope=docker-amd64, linux/amd64, ubuntu-latest-32-core) (push) Has been cancelled
Docker Build, Test, and Publish / publish (arm64, type=gha,scope=docker-arm64, type=gha,mode=max,scope=docker-arm64, linux/arm64, ubuntu-latest-32-arm-core) (push) Has been cancelled
Nix flake check / nix flake check (push) Has been cancelled
The chat header is display:none inside the pane tree (title lives in the
zone tab), so the header cwd segment never shows in the main layout.
Append displayPath(cwd) to the always-visible workspace strip instead.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-09-18 19:32:46 +08:00
m4 7025584b9f feat(desktop): pin AI-content disclaimer under the composer
Registered as a core composer.underside contribution so the chrome-free
strip auto-hides when empty and plugins can sit beside the line.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-09-18 19:17:06 +08:00
m4 6946e37f96 feat(desktop): surface produced files, session artifacts fold, header cwd
Completed diff-less writes (write_file creates) were invisible in the
transcript. They now appear in the per-turn files card with a "new" tag
(preview on click, system-app open on hover), a collapsible per-session
artifacts fold sits above the usage footer, and the chat header shows
the session's workspace path ahead of the title.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-09-18 19:16:57 +08:00
m4 9845e0b262 fix(desktop): resolve session usage footer by stored id with lineage match
CI / Check no case-colliding filenames (push) Has been cancelled
CI / package-lock.json diff (push) Has been cancelled
CI / Lint Docker scripts (push) Has been cancelled
CI / Supply-chain scan (push) Has been cancelled
CI / Review label gate (push) Has been cancelled
CI / All required checks pass (push) Has been cancelled
CI / Check contributors (push) Has been cancelled
CI / Check uv.lock (push) Has been cancelled
CI / Check no committed infographics (push) Has been cancelled
CI / Profile artifact check (push) Has been cancelled
CI / Detect affected areas (push) Has been cancelled
CI / Python tests (push) Has been cancelled
CI / OS-specific tests (push) Has been cancelled
CI / Python lints (push) Has been cancelled
CI / JS & TS checks (push) Has been cancelled
CI / Installer tests (push) Has been cancelled
CI / Rust tests (push) Has been cancelled
CI / Desktop E2E (push) Has been cancelled
CI / Docs Site (push) Has been cancelled
CI / Deny unrelated histories (push) Has been cancelled
CI / CI timing report (push) Has been cancelled
Docker Build, Test, and Publish / Detect affected areas (push) Has been cancelled
Docker Build, Test, and Publish / build (amd64, type=gha,scope=docker-amd64, type=gha,mode=max,scope=docker-amd64, linux/amd64, ubuntu-latest-32-core) (push) Has been cancelled
Docker Build, Test, and Publish / build (arm64, type=gha,scope=docker-arm64, type=gha,mode=max,scope=docker-arm64, linux/arm64, ubuntu-latest-32-arm-core) (push) Has been cancelled
Docker Build, Test, and Publish / publish (amd64, type=gha,scope=docker-amd64, type=gha,mode=max,scope=docker-amd64, linux/amd64, ubuntu-latest-32-core) (push) Has been cancelled
Docker Build, Test, and Publish / publish (arm64, type=gha,scope=docker-arm64, type=gha,mode=max,scope=docker-arm64, linux/arm64, ubuntu-latest-32-arm-core) (push) Has been cancelled
Docker Build, Test, and Publish / merge (push) Has been cancelled
auto-fix lint issues & formatting / Generate eslint --fix patch (push) Has been cancelled
auto-fix lint issues & formatting / Apply patch (push) Has been cancelled
Nix flake check / Detect affected areas (push) Has been cancelled
Nix flake check / nix flake check (push) Has been cancelled
Deploy Site / deploy-vercel (push) Has been cancelled
Deploy Site / deploy-docs (push) Has been cancelled
Build Skills Index / build-index (push) Has been cancelled
Build Skills Index / trigger-deploy (push) Has been cancelled
CDP verification on the live app showed the footer never rendered: ChatView
passed the runtime id (view.$runtimeId) while $sessions rows key off stored
ids, and compression chains hand the view a lineage id rather than the row's
own id. Look up with selectedSessionId || routedSessionId and
sessionMatchesStoredId, same as ChatHeader.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-09-18 17:34:54 +08:00
m4 71b37dd42d feat(desktop): render session usage footer at transcript end
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-09-18 17:08:49 +08:00
m4 917290bec2 feat(desktop): add SessionUsageFooter component and i18n keys
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-09-18 16:50:10 +08:00
m4 74fa6881ea style(desktop): fix import order in office-open touched files
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-09-17 23:08:53 +08:00
m4 526b13170d test(desktop): satisfy Translations typing and lint rules for office-open tests
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-09-17 23:08:24 +08:00
m4 45dc96b139 feat(desktop): binary refusal page offers the system app first
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-09-17 22:57:33 +08:00
m4 a1f9e97782 feat(desktop): double-click office files opens them in the system app
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-09-17 22:51:07 +08:00
m4 4379bf6d0b feat(desktop): openFileWithSystemApp entry with office whitelist
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-09-17 22:41:23 +08:00
m4 c25a3748bb feat(desktop): hermes:fs:openExternal IPC with receipt-returning OS open
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-09-17 22:35:34 +08:00
m4 3ca91c55f3 feat(desktop): openExternalFileForIpc opens files via OS handler
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-09-17 22:28:07 +08:00
brooklyn! 1331053fcf style(desktop): anchor composer icon tooltips beside the control
Tips on the composer's row controls open to the left so they never cover
the fanned discs or the input; the model and reasoning pills keep theirs
centred above. A left-anchored Tip rags its wrapped lines toward the
trigger, in the primitive rather than per call site.
2026-09-16 02:56:57 -05:00
brooklyn! bc722dcb85 feat(desktop): fan the composer's voice toggles out of the mic
The docked composer spent three icon buttons on toggles that are set once
and rarely touched. The mic is now the one button in the row; hovering it
fans spoken-replies and the wake word out above it. The mic reports
dictation only — the wake word carries its own on-state on its own disc,
so mirroring it onto the mic read as dictation being on.

The wake disc's tip names the phrase and nothing else; the pressed state
says on/off. The folded HUD/narrow-tile VoiceMenu is unchanged.
2026-09-16 02:56:57 -05:00
brooklyn! c7580f0e06 feat(desktop): FanMenu primitive and a floating Button variant
One hub control that fans its sibling toggles out on hover — a column, a
row split around the hub, or an arc — with the discs portalled past any
overflow-hidden parent and re-anchored on scroll and resize. Hover state,
geometry and open/close timing live in the primitive so a consumer only
re-renders when its own items change.

A document-level pointer watchdog closes the fan when enter/leave is
skipped: a disc that goes disabled under the pointer (a toggle turning
pending right after its click) stops receiving pointer events, so its
pointerleave never fires and the fan stayed open.

Discs wear the new Button `floating` variant off (popover fill +
shadow-md, glyph-only hover) and `default` on, so a toggled state is an
opaque primary disc rather than a translucent tint.
2026-09-16 02:56:57 -05:00
brooklyn! 65b622da0d fix(desktop): transcript directives survive markdown, and the guide keeps its reasoning to itself
A handoff directive whose brief read as markdown (*by week*, a_b c_d, ~/x)
split the paragraph into element children, so the card never claimed it and
the raw ::onboarding{task="…"} line painted as the user's own message.
Directive lines are now backslash-shielded in preprocessMarkdown, next to
the inline-code and math shields, and reach the renderer as one text node.

The guide's reasoning is it reading its own runbook ("Now step 4: offer the
tour with ::ask"); shown under the greeting it breaks the conversation the
guide is trying to have. Reasoning disclosures stay hidden on the guide
thread only.
2026-09-16 02:49:21 -05:00
ouyangbo 012c9c6bed chore: anchor fresh-start history to upstream 2026-09-16 15:06:54 +08:00
brooklyn! 2e320e6d1a fix(desktop): keep inline edit placeholders off entered text 2026-09-16 02:04:58 -05:00
brooklyn! 2b7292ff0f style(desktop): frame inline subagents with a subtle outline 2026-09-16 01:44:33 -05:00
brooklyn! 3bdd4cc5fd fix(desktop): keep background continuations in one visual response 2026-09-16 01:44:33 -05:00
brooklyn! 57d34b14c2 fix(desktop): keep completed subagents from reviving stale activity 2026-09-16 01:44:33 -05:00
teknium1 10652c9345 fix(desktop): classify any 3xx as a redirect and name its Location
fetchJson/fetchPublicJson only reached the redirect diagnostic when the 3xx
carried an HTML body or text/html content-type; an empty-body 302/307 (the
common reverse-proxy / forward-auth shape) still resolved null through the
earlier empty-body check. http.request never follows redirects, so classify
on status first and reject every 3xx with the redirect error regardless of
body.

Pass res.headers.location through so the message says where the request was
sent, and stop blaming credentials when the Location differs from the
requested URL only by scheme or trailing slash -- that is a saved-URL
mismatch, not an authentication proxy. Drop the 404 mention from the
docstring/test: both callers reject >= 400 before this branch, so only the
2xx leg carries the endpoint-missing capability wording.

Part of #112072
2026-09-15 19:10:53 -07:00
teknium1 c902f50efb fix(desktop): send the connection extra gateway headers on remote media streams
createMediaProtocolHandler() set only the session token / bearer on the
/api/files/stream request. The descriptor it resolves now carries the
connection's extra gateway headers, but the handler never read them, so
attachments in session history from a header-gated remote still bounced off
the access proxy even though every fetchJsonForBackend() call got through.

Merge connection.headers into the media request before auth, letting the
forwarded range/cache negotiation headers win, and pin it on both the
token and the OAuth cookie-session legs.

Part of #112072
2026-09-15 19:10:53 -07:00
teknium1 47c3683f23 fix(desktop): stop calling a 3xx HTML reply a missing endpoint
The JSON guard in fetchJson/fetchPublicJson blamed every HTML reply on a
missing backend endpoint. A 3xx HTML body is an access proxy redirecting
to its login page: the endpoint exists, the credentials never arrived.
Besides misleading the user, the wording is the capability signal that
isMissingHealthEndpointError and the renderer's gateway-rpc predicate key
on, so an auth redirect was silently classified as "endpoint missing" and
routed onto compatibility paths instead of surfacing as an error.

Build the error in api-transport.ts (where the sibling httpStatusError
lives) and pick the hint by status: 3xx names the redirect and points at
the saved token/extra headers; everything else keeps the endpoint-missing
wording the predicates rely on.

Part of #112072
2026-09-15 19:10:53 -07:00
teknium1 e65ddf1c7b fix(desktop): keep primary remote gateway extra headers on REST calls
createPrimaryRemoteConnection() rebuilt the primary remote descriptor
field by field and left out `headers`, so every REST call routed through
fetchJsonForBackend() (Settings profiles/config, session history) reached
the gateway without the configured extra headers while chat, the Test
button and the readiness probe -- which read the exact-URL WebSocket header
store or the resolved route directly -- kept working. Behind an access
proxy (e.g. a service-token gate) those REST calls came back as a 302 to
the login page.

Carry `headers` through the descriptor like every other rebuild site
(buildRemoteConnection, the registry pool path and both ensureRegistryBackend
reuse branches already spread it), and pin it with an invariant test on the
existing primary-descriptor seam.

Fixes #112072
Co-authored-by: plluviera <plluviera@users.noreply.github.com>
Co-authored-by: KoNit-K <124019182+KoNit-K@users.noreply.github.com>
2026-09-15 19:10:53 -07:00
teknium1 66f9f3692a fix(desktop): share the profile-switch freshness latch across font settings and MCP tab
Extract useProfileSwitchLatch(query stamps) and reuse it in ChatFontSetting,
TerminalFontSetting and McpTab instead of three divergent dataUpdatedAt
copies. The MCP tab keeps its release-on-fresh-error behaviour via the
optional errorUpdatedAt stamp; the font settings keep data-only semantics.
2026-09-15 19:10:25 -07:00
teknium1 92a6639e84 refactor(desktop): fold the font reseed latch into one dataUpdatedAt stamp
The previous commit tracks "waiting for the next config fetch" with a
`profilePending` state, a `staleConfigStamp` ref and a second effect that
clears the flag once `dataUpdatedAt` moves. The same guarantee fits in the
seed effect itself: the profile-switch handler stores the query's current
`dataUpdatedAt` as `staleStamp` and the seed effect refuses to reseed while
`dataUpdatedAt === staleStamp`. One state cell instead of state + ref +
effect, no `no-restricted-syntax` ref write in an effect, and the stale
guard is unchanged: the previous profile's cached record carries the
recorded stamp, so it can never repaint the new profile; only a fetch that
lands after the switch bumps the stamp and seeds.

Co-authored-by: danrudy33 <danrudy33@users.noreply.github.com>
2026-09-15 19:10:25 -07:00
KoNit-K df832c86a2 fix(desktop): reseed font controls after config refetch 2026-09-15 19:10:25 -07:00
teknium1 abdb402701 fix(mcp): carry the lazy status across the TUI wire, tests and docs
Follow-up to the ported status fix:

- `tui_gateway/contracts/tools_mcp_plugins.py::McpRuntimeStatus` is a
  closed wire enum; `mcp.servers.status` would raise `ContractViolation`
  on the new `lazy` value. Declare it and regenerate the TS/OpenRPC
  contract files.
- `ui-tui` session panel: an unknown status fell through to the red
  `failed` branch; render `lazy` with its cached tool count (inline
  branch, no component extraction).
- Two invariant tests, both red on origin/main: the real discovery path
  yields `status: lazy` with the cached tool count and a summary without
  `failed` (eager control stays `configured`, live control stays
  `connected`); a lazy-only run neither warns nor re-arms the startup
  retry, while a configured-only run still does.
- Document the per-server `lazy` key (undocumented until now) in
  `cli-config.yaml.example`, the MCP config reference and the MCP guide.
2026-09-15 19:06:54 -07:00
teknium1 837acdc91d fix: share the control-frame opener list and cover [System:/[IMPORTANT:/[PRIOR CONTEXT/[CONTEXT SUMMARY]
Review finding on #112260: the hosted-room member relabel regex was a third
hand-copied opener list that missed the frames context_compressor and
title_generator already treat as harness input, so a member reply starting
with "[System: ..." or "[IMPORTANT: 2 background processes ..." reached peers
in its exact trusted shape. agent.prompt_builder.CONTROL_FRAME_OPENERS is now
the single source; the gateway regex is built from it and the desktop TS
literal mirrors it byte-for-byte.
2026-09-15 19:04:59 -07:00
teknium1 9988545a78 fix(gateway,desktop): one visible relabel for member-quoted control frames on both room surfaces
Follow-up to the two cherry-picked contributor commits (#111571 gateway, #111576 Desktop),
which neutralized the same class with two different mechanisms: an invisible U+200B after
the `[` on the gateway path and a phrase replacement ("RESERVED CONTROL MARKER NEUTRALIZED")
on the Desktop path.

Both room-transcript builders now share one frame set (the mid-turn steer marker open/close,
the compaction handoff, runtime/system notes, planning-state and async-delegation frames —
the same openers agent/title_generator and agent/context_compressor already classify as
harness-authored, case-insensitive) and one visible relabel: the opener `[` becomes
`[member-quoted `. The peer still reads what the member wrote, but the exact trusted shape
the system prompt tells the model to honour is gone and the label says who authored it.
A zero-width space is invisible to a human reading the transcript and easy for a model to
skip over; the visible label is not.

Genuine user lines, stored room events and the displayed message are untouched on both
surfaces (probed live: stored member event byte-identical, `User (user):` line verbatim).
Tests trimmed to one invariant per surface, built from agent.prompt_builder's real marker
constants on the Python side.

Co-authored-by: KoNit-K <124019182+KoNit-K@users.noreply.github.com>
Co-authored-by: Hukla <129692708+huklaa@users.noreply.github.com>
2026-09-15 19:04:59 -07:00
Hukla 498633f4ec fix(desktop): neutralize member control markers 2026-09-15 19:04:59 -07:00
teknium1 8550f9084e docs(profiles): Desktop cron ticker follows profile create/delete live
Also satisfy padding-line-between-statements on the two salvaged hunks.
2026-09-15 18:54:28 -07:00
teknium1 1220491468 chore(desktop): keep the slot-storm fix to the retry backoff
Drop the extra assertLocalProfileCanStart call added ahead of the slot
queue: the deleted-profile fence already runs at the spawn boundary below
and is not the mechanism behind the #111338 retry storm.
2026-09-15 18:54:28 -07:00
KoNit-K 68e4833134 fix(desktop): bound background profile hydration retries 2026-09-15 18:54:28 -07:00
teknium1 05051691c6 test(desktop): trim the archived-view reload coverage to two invariants
Keep the two discriminating cases (a sessions.changed tick reloads the archived
set while the view is open; a failed refresh retains the last good rows) and
drop the closed-view control, which passes on the unfixed base as well.
2026-09-15 18:54:00 -07:00
KoNit-K dbda53b8be fix(desktop): refresh archived sessions on external changes
Co-authored-by: DavidMetcalfe <80915+DavidMetcalfe@users.noreply.github.com>
2026-09-15 18:54:00 -07:00
teknium1 a40d90e9be test(desktop): trim the voice-live toast tests to two invariants
Seven per-case tests collapsed to two: one per behaviour class (our own
close reasons → copy, server reasons verbatim; mic DOMException → recorder
copy, non-mic failures untouched). Source is byte-identical to the
contributor commit. Dropped: the `closed`/blank-reason case, the
`close_requested` filter (pre-existing behaviour), and the per-name
DOMException matrix — the mapping table lives in `micError`, asserting one
name proves the live path routes through it.
2026-09-15 18:53:32 -07:00
finn763 c2625370d7 fix(desktop): stop the voice-live toasts leaking machine strings (#111987)
The session-end toast printed the raw wire reason (`connection_lost (127s)`,
`closed`) and a denied `getUserMedia` reached the toast as bare `DOMException`
text, while the recorder path already had friendly copy for those names.

- `liveEndedMessage` (new, exported for the tests) maps our own close reasons —
  `connection_lost`, `closed`, plus a blank reason — to i18n copy; server-sent
  reasons stay verbatim (unbounded, no redaction claim).
- `micError` is exported and reused on the live start path, so a mic
  DOMException gets the recorder's copy; an unmapped DOMException name now falls
  back to `microphoneStartFailed` instead of its raw text.
- The start catch maps DOMExceptions only: non-mic failures ('GPT-Live session
  already started', 'Missing local SDP offer', API errors) keep their message.

New i18n keys: `notifications.voice.liveEndedConnectionLost` / `liveEndedClosed`
(en base + zh translation; the other locales fall back to en).

Tests: `use-voice-live-conversation.test.ts` drives the real toast store through
a fake transport — reason copy, blank/unknown reasons, `close_requested` filter,
mic DOMException names, and untouched non-mic failures.
2026-09-15 18:53:32 -07:00