Commit Graph
119 Commits
Author SHA1 Message Date
dd3xp 633e8111a8 fix(desktop): bridge WS auto-reconnect + visibilitychange handler
When mobile browser is backgrounded the OS pauses/kills WebSocket; on

return the page stays on a dead connection and the next send shows

"bridge 未连接". Conductor's WS already had reconnect+backoff; bridge

did not.

Added to bridge WS:

- close handler now schedules reconnect with exponential backoff

  (1s, 2s, 4s, ... capped at 30s)

- visibilitychange listener: when page becomes visible again and ws is

  closed, reset retry counter and reconnect immediately

- wsRetries resets on successful open

- skip retry while page is hidden (battery saver)

Bump app.js?v=86 -> 87.
2026-06-04 00:00:44 +08:00
dd3xp 39c96744d4 fix(desktop): CONDUCTOR_ORIGIN follows location.protocol (not hardcoded http)
BRIDGE_ORIGIN already used ${location.protocol}//; CONDUCTOR_ORIGIN was

hardcoded to http://, which would have broken under HTTPS deployment

with a Mixed Content block. Now both behave consistently — page over

HTTPS uses https for conductor calls and wss for the WS already (the

WS constant was already correct).

Triggered by SakuraFrp requiring HTTPS access (TCP tunnels reject

plain HTTP with 501). Tunnels now run with 自动 HTTPS enabled, so

browser hits https://...:14168 / :18900, and frontend needs to use

https in its constructed conductor URL.

Bump app.js?v=84 -> 86 (skipping 85 — that was an auth-gate-only bump).
2026-06-02 22:26:53 +08:00
dd3xp c45d7b86fb refactor(desktop): centralize bridge/conductor port + URL into constants
Per teacher request, pull the 14168 / 8900 magic numbers and the URL

construction out of ~17 inline call sites into a single block at the top

of app.js:

  const BRIDGE_PORT = 14168;

  const CONDUCTOR_PORT = 8900;

  const BRIDGE_ORIGIN = `...`;        // http(s)://host:14168

  const BRIDGE_WS_ORIGIN = `...`;     // ws(s)://host:14168

  const CONDUCTOR_ORIGIN = `...`;     // http://host:8900

  const CONDUCTOR_WS_ORIGIN = `...`;  // ws(s)://host:8900

All fetch / WebSocket call sites now use those origins. No behavioral

change — bridge still calls 14168, conductor still calls 8900. Sets up

future fixes (same-origin bridge, bridge-proxied conductor, runtime port

swap) to be a one-line change in the constants block.

Bump app.js?v=83 -> 84.
2026-06-02 21:27:15 +08:00
dd3xp 2e64539ec5 feat(desktop): per-page top bar with caret toggles + drop annotation scaffold
1. Removed the two floating arrow buttons (.sb-toggle / .rp-toggle) that

   used to sit at the side seams between sidebar/main/rightpanel.

2. Each page section now owns its own .page-top bar with:

   - left: .pt-sb-toggle (caretLeft, borderless icon button) — collapses

     left sidebar; svg rotates 180° when sidebar is collapsed.

   - right: .pt-rp-toggle (caretRight) — same logic for right panel.

   - chat/collab keep run-state centered between the two icons.

   - services/token use a .pt-spacer to fill the middle gap.

3. .pt-icon style is borderless / transparent / opacity-0.7 (no boxy

   bordered button look); page-top padding tightened to 4px so the

   carets hug the screen edges. Bump styles.css?v=95→97.

4. Wiring: app.js queries .pt-sb-toggle/.pt-rp-toggle by class (4 of

   each, one per page) and binds them to the existing

   .body.classList.toggle('sb-collapsed') / .toggle('rp-collapsed')

   handlers. Behavior identical to the old single buttons.

5. Dropped the DEV annotation scaffold: removed annot.css link in head,

   annot.js script at end of body, and deleted both files.
2026-06-02 07:52:36 +08:00
dd3xp 2d003d7210 Merge main into RoundSquisheen: catch up with PR#7 services tabs + 3 visual changes + cache buster bumps 2026-06-02 07:40:43 +08:00
dd3xp 94477092b4 chore(desktop): bump styles.css?v=93→94 to flush stale CSS cache
Previous commit changed .tok-tabs/.tok-tab/.tok-chart CSS but did not bump the styles.css version, so the browser kept serving the cached v=93 file and the visual changes (underline tabs, taller chart) did not appear in the page.
2026-06-02 07:27:53 +08:00
dd3xp c27be25cc7 feat(desktop): nav reorder + taller trend chart + token tabs use svc style
1. Sidebar nav: move 后台服务 (services) to AFTER 指挥家 (collab).

   New order: 聊天 → 指挥家 → 后台服务 → Token 统计.

2. Token trend chart: was flat (container 160px tall, viewBox 600×140).

   Now container 280px + max-width 760px to stop it stretching on wide

   screens; viewBox bumped to 600×260 with a bit more padding so text

   does not get distorted under preserveAspectRatio="none".

3. Token stats tabs (聊天 / Conductor) reuse the .svc-tabs underline

   look from the services page — same visual language. CSS-only;

   .tok-tabs/.tok-tab classes and the JS click handler are unchanged.

4. Bump app.js?v=81→82 (app.js really changed this time, and the bump

   also flushes stale i18n cache for previously-untranslated keys).
2026-06-02 07:25:25 +08:00
dd3xp 65a54a3f09 Merge PR #7: feat: merge channels and status into one services page
Resolved one conflict in app.js: kept the new token trend chart code from

main and adopted PR's services-tab nav handler (replaces the old

channels/status separate handlers, which the PR consolidates anyway).

index.html and styles.css auto-merged cleanly.

Closes dd3xp/GenericAgent_Desktop#7
2026-06-02 06:50:01 +08:00
yiqi-017 21231c653b feat(desktop): add collapsible daily cost trend chart to token stats
Pure SVG line chart showing daily spending (¥) over time. Respects
date filter, fills zero-cost gaps, uses local timezone for grouping.
Hidden on Conductor tab.
2026-06-02 04:23:00 +08:00
yiqi-017 243645e5e6 i18n(desktop): localize conductor token stats and pricing disclaimer 2026-06-02 03:58:13 +08:00
weaselkkk fa8daff383 feat: merge channels and status into one services page 2026-06-01 22:06:14 +08:00
yiqi-017 0c45c86a42 feat(desktop): token stats tab bar separating chat and conductor
- Two tabs: 聊天 (chat sessions) and Conductor (cumulative/current)
- Conductor tab hides date filter and stat-row summary
- Remove green background and expand triangle from conductor rows
- Bump app.js and styles.css cache versions
2026-06-01 19:31:41 +08:00
dd3xp bd6f0d7be5 chore(desktop): remove preset entry from conductor + menu (preset is chat-only) 2026-06-01 17:12:31 +08:00
yiqi-017 d66f84e0d3 style(desktop): use conductor SVG icon in token stats rows 2026-05-30 22:13:41 +08:00
China Nikocado Avocado d5dbdf6984 Merge pull request #6 from dd3xp/Conductor前端优化
Conductor美化
2026-05-30 19:45:29 +08:00
lyx a6f3e9c7e9 Conductor美化
Conductor 页 UI 重构:对齐主聊天布局,复用消息/composer 样式,独立 cdb-composer 与 progress rail/drawer。
2026-05-30 19:09:37 +08:00
yiqi-017 febd3d86fc fix(desktop): conductor token accumulation loop on refresh
Always overwrite last snapshot with current values (even zero) so
restart detection only triggers once instead of every refresh.
2026-05-30 00:06:54 +08:00
yiqi-017 7223a0d2ec fix(desktop): update model pricing + add pricing disclaimer
- o4-mini: .10/.40 -> /usr/bin/bash.55/.20 (price drop)
- deepseek-v4-pro: /usr/bin/bash.55/.19 -> /usr/bin/bash.435//usr/bin/bash.87 (permanent 75% cut)
- Add claude-opus-4-8 at /5
- Add disclaimer: pricing may vary by API provider
2026-05-29 23:46:58 +08:00
yiqi-017 90960679b9 feat(desktop): persist conductor token stats via bridge file storage
Two rows: cumulative total (survives conductor restart) and current
session. Restart detection via value comparison; data stored alongside
bridge token history in desktop_token_history.json.
2026-05-29 23:40:34 +08:00
yiqi-017 b53f107e6e fix(desktop): skip token delta recording while session is busy
Prevents token records from splitting into two entries when polling
occurs mid-generation. The full delta is captured on the next poll
after the session becomes idle.
2026-05-29 23:09:47 +08:00
yiqi-017 90a37236aa feat(desktop): conductor token stats summary row in token page
- conductor.py: install cost_tracker + expose /token-stats endpoint (5 lines)
- app.js: fetch conductor token totals and display as a single summary row at top of token table (not expandable, with tooltip noting it's excluded from cumulative totals)
- styles.css: conductor row styling
2026-05-29 23:03:53 +08:00
yiqi-017 db7dd70ab3 fix(desktop): token stats title fallback when sess.title is empty
两个修复:

1. tokRenderTable 里 title 显示修复 — 新的 session naming 把 sess.title 默认设为空字符串,导致 token 统计 fallback 到原始 session ID(sess-xxx)。改为用 displayTitle(sess) 实时推导标题,和侧边栏一致。
2. tokPollBridge 里写入 history 时的 title 修复 — 同样的问题,写入时 sess?.title || sid 对空标题 fallback 到 ID。改为 sess ? displayTitle(sess) : sid。
2026-05-29 18:36:08 +08:00
dd3xp e5b80d1003 feat(desktop): preset/composer/topbar restructure + conductor persistence + TUI-style session naming
UI restructure (frontend static):
- PLAN moved from sticky toggle chip to a preset card (BUILTIN_PRESETS) that
  one-shot-sends `presetPrompt.plan`, now pointing at the real
  memory/plan_sop.md (Auto was considered too but dropped — it semantically
  overlaps with the existing "自主探索" preset). All plan/auto toggle
  plumbing removed: state, chip listeners, applyToggleClass, ga_plan/ga_auto
  localStorage, planPrefix/autoPrefix injection.
- Chat composer: model chip moved out of the joined .cb-left pill group to
  sit next to the send button (composer-bot is now right-aligned model+send).
- Conductor composer: gained its own #collab-model-chip + #collab-model-menu;
  openModelMenu/renderModelMenu/updateModelChip refactored to be ctx-aware
  (both chips share the model list; each pops its menu into its own
  composer; updateModelChip syncs both names).
- Topbar dissolved into per-page headers: the global .topbar was removed
  from <main>; the run-state moved into a .page-top inside the chat page,
  so the "topbar" now switches with the page instead of persisting.
- Removed the conductor "{n} 个任务进行中" sticky banner (#collab-sticky);
  the same info is already in the progress panel and the sidebar badge.

Conductor persistence (conductor.py + frontend wiring):
- conductor.py: add_chat() carries files/images on each chat item; WS
  receive passes data.files/data.images through; hello includes a
  running flag (any subagent with status="running"). 5 net edits.
- app.js: ws.send now posts {msg, files, images} (was msg only); onWsData
  hello/chat branches map files/images and set S.conductorTyping from
  data.running so attachments + run animation survive a page refresh.

Session naming (mirror TUI continue_cmd._preview_text):
- New helper displayTitle(sess): if user manually renamed, use sess.title;
  otherwise scan messages — prefer the last <summary>…</summary> in any
  assistant reply, fall back to the first user message text (≤40 chars,
  attachment placeholders stripped), final fallback t('conv.defaultTitle').
- newSession() now defaults sess.title to '' instead of '新对话'; the
  earlier "first message → title" auto-rename block in submitInput is
  gone — titles only get written when the user renames explicitly.
- isAutoTitle() recognises '新对话'/'New chat'/'agent-N' as placeholder so
  legacy sessions and the brief agent-N experiment get re-derived live
  in the sidebar without losing user renames.
- Sidebar render + search filter now go through displayTitle.

Note: requires a one-time restart of conductor.py for its part to take
effect; the static frontend changes are just a refresh.
2026-05-29 02:22:16 +08:00
China Nikocado Avocado eefd60e074 Merge pull request #4 from dd3xp/feat/input-length-limits
feat(frontend): add input length limits to all text fields
2026-05-28 21:12:18 +08:00
HYC-hsy f540515f0c feat(frontend): add input length limits to all text fields 2026-05-28 21:01:59 +08:00
dd3xp ab9fbea3c1 chore: gitignore local BUG_*.md bug/limitation drafts 2026-05-28 04:34:19 +08:00
dd3xp 77c6adc09a feat(desktop): inline attachment chips in messages + fix conductor raw-path bubble
- Render [Image #N]/[File #N] placeholders as inline chips in-place (filename)
  in user messages, so you can see where an attachment sits in the text. Image
  thumbnails + file cards are unchanged. Applies to chat and conductor via a
  shared renderMsgTextWithChips() helper; conductor messages now carry sid+name
  so the chip can resolve a filename.
- Conductor: stripAttach() also strips inline desktop_uploads paths, and pushMsg
  folds the server echo into the local optimistic message (keep clean text +
  chips/cards, drop the raw path) so conductor matches chat instead of showing a
  second bubble with the full local upload path.

Known limitation (backend, not in scope here): conductor attachments + running
state don't survive a page refresh — conductor.py only stores/sends
{id,role,msg,ts,read} with no file refs and no run state, so the frontend can't
restore them on reload. Persisting those belongs to the conductor maintainer.
2026-05-28 04:27:37 +08:00
dd3xp 002c1851cf chore: remove dev_notebook.md (dev scaffold merged in via PR#5) 2026-05-28 03:58:53 +08:00
China Nikocado Avocado d9488ec2a1 Merge pull request #5 from wjl2023/feat/frontend-ui-polish
feat: 前端UI优化 - 方形设计风格 + 代码块/LaTeX/滚动条/ask_user增强
2026-05-28 03:57:54 +08:00
wjl2023 0672d70358 feat: ask_user通知框去圆角,改为方形
- .ask-user-notice border-radius: var(--radius) → 0
- 匹配项目整体方形设计风格
2026-05-28 03:41:43 +08:00
wjl2023 f4f9bd35cb feat: ask_user通知加粗banner和问题文本
- .ask-user-banner-text font-weight: 600→700
- .ask-user-body 新增 font-weight:600
- 提升ask_user卡片视觉层级,问题更醒目
2026-05-28 03:40:13 +08:00
wjl2023 b3ade6b3e7 feat: 自定义滚动条样式,完全方形窄滚动条
- 全局 webkit scrollbar: 6px宽,border-radius:0(完全方形)
- 滑块颜色 var(--line),hover 加深为 var(--line-strong)
- 轨道透明,不占视觉空间
- 去掉 scrollbar-width:thin(会覆盖webkit伪元素导致overlay模式)
- 匹配项目整体方形设计风格
2026-05-28 03:36:38 +08:00
wjl2023 83706247e4 feat: 精简分割线,聊天主体用单一矩形框包裹
- msg-area 四边 border:1px solid var(--line) 形成完整矩形框
- 去掉 topbar border-bottom(改由 msg-area border-top 承担)
- 去掉 composer border-top(改由 msg-area border-bottom 承担)
- 去掉 main.main 的 border
- 去掉 .sidebar-foot 的 border-top
- 去掉 aside.sidebar 的 border-right
- 去掉 #rightpanel 的 border-left
- 去掉 .chat-tools 的 border-bottom
- 矩形完全自包含于 msg-area,不受 rightPanel 遮挡影响
2026-05-28 03:28:48 +08:00
wjl2023 071edcfc76 style: align LaTeX copy button with code block copy button
- Replace SVG icon with ⧉ character (same as code block)
- Match font-size, padding, border-radius, background
- Remove border and flex layout, use simple text button
- Both buttons now visually identical (~16.5x14.7px)
2026-05-28 03:17:55 +08:00
wjl2023 15415a6b75 fix(latex): support \(...\) \[...\] delimiters and protect code blocks
- Add \(...\) and \[...\] as recognized LaTeX delimiters in protectLatex
- Protect fenced code blocks and inline code before LaTeX extraction
- Prevents $...$ inside code blocks from being misinterpreted as math
- Processing order: protect code → extract LaTeX → restore code → marked.parse
2026-05-28 03:12:55 +08:00
wjl2023 b260ff7326 feat: TUI风格代码块渲染 - 语言标签头+复制按钮+终端面板样式 2026-05-28 03:06:15 +08:00
wjl2023 d1e18bab8b feat: 折叠框箭头旋转动画(▶→▼, 0.2s ease transition) 2026-05-28 03:01:20 +08:00
wjl2023 4d0a911187 fix: 去掉工具调用/结果折叠框的蓝绿色边框和背景(fold-tool/fold-result→transparent) 2026-05-28 02:58:08 +08:00
wjl2023 10734386e6 fix: 去掉模型回复的灰色气泡背景(bubble.md background→transparent) 2026-05-28 02:54:39 +08:00
dd3xp 492caa610e fix(desktop-bridge): apply mykey edits to live agents without restart
Editing a model key / adding a profile wrote mykey.py but the running session
agents kept using the LLM sessions built at startup (old key), so the change
only took effect after a restart.

Root cause: llmcore tracks "changed since last load" via a single global mtime
flag, and load_llm_sessions() skips rebuilding when changed=False. Whichever
agent reloads first consumes that flag — e.g. the throwaway GenericAgent the UI
spins up to render the model list — so the real persistent session agent later
sees changed=False and keeps its stale sessions.

After saving a profile, force every live session agent to rebuild: reset
llmcore._mykey_mtime to None before each agent.load_llm_sessions() so
reload_mykeys() reports changed=True. Bridge-only (same trick as the existing
_invalidate_mykey_cache); no core changes to agentmain/llmcore; the rebuild
preserves conversation history via agentmain's oldhistory hand-off.
2026-05-28 01:22:07 +08:00
dd3xp a8e76450b8 feat(desktop): adopt PR#3 rectilinear design + clearer PLAN/AUTO + session restore
Re-skin the desktop frontend in ethan su's "rectilinear workspace" visual
language (PR#3) without dropping any feature, plus two UX fixes. Done as a
content-overlay, NOT a git merge of PR#3 — PR#3's app.js reverts ask_user /
conductor / composer / timing, so only its visual layer is adopted.

Design (PR#3):
- Bundle brand fonts (Azonix wordmark / Lexend / Noto Sans / JetBrains Mono)
  + phosphor-icons.js (auto-hydrates [data-ga-icon]).
- styles.css: adopt ethan's full design-token system (accent #1f6f53,
  --radius 4px/2px squared corners, brand fonts) via 3-way merge; keep all
  feature CSS (composer chips, ask_user notice, conductor, flatpickr, timing
  badge); normalize leftover --blue -> --accent.
- index.html: ethan's phosphor chrome; keep contenteditable composers, the
  real conductor UI, flatpickr links, and collab-badge.
- app.js: add GA_ICON() helper; swap dynamic chrome icons (pin, more, model
  edit/delete, add-preset, channel, ctx-delete, drawer-close) to Phosphor.
  Flags, copy/check, file-chip and preset-card icons left inline by design.

Fixes:
- PLAN/AUTO toggles now show an unmistakable on-state (solid accent fill);
  the .cb-left .chip.sm rule was overriding .chip.on by specificity, so the
  on/off difference was nearly invisible.
- On refresh, restore the session you were actually viewing (persist
  ga_active) instead of the bridge's roaming most-recently-updated session;
  show the empty new-session state when none is selected.
2026-05-28 01:22:07 +08:00
dd3xp 875e6614a4 refactor(ask_user): treat single-question as a special case of multi-question
Unify the single-question and multi-question ask_user rendering instead of
having two divergent paths:

- Single-question options (from `candidates`) are now folded into the question
  body as inline A./B./C. lines via foldAskCandidates(), rendered exactly like
  multi-question inline options (.ask-option-line). The separate numbered <ul>
  candidate list is gone, which also removes the "1. A." double-numbering.
- Fold with a single newline so question + options render as one <p>; every
  option (including the first) follows a <br>, so all get consistent indent.
- Placeholder is unified to the free-form ask.placeholderOpen for both; the
  per-single-question "type 1/2/3 to pick" placeholder is removed.
- Drop now-dead code: ask.placeholderOpts i18n (zh+en) and the
  .ask-candidates / .ask-candidate-key / .ask-candidate-label CSS.
2026-05-27 23:04:32 +08:00
dd3xp 51c0330621 merge: fold latest main (ask_user + session-rename) into contenteditable composer
- Resolve styles.css: keep session-rename's .ci-rename-input + my .ci-pin, both on --accent.
- Adapt ask_user dynamic placeholder: inputEl.setAttribute('placeholder',...) ->
  'data-ph' so it shows on the contenteditable composer (no placeholder attr on a div).
- session-rename uses its own rename <input> (.value) — untouched, no composer conflict.
- Bump asset cache-bust (styles.css v74 / app.js v45).
2026-05-27 21:55:51 +08:00
dd3xp 48d26ac4d2 merge: reconcile desktop/main (conductor + ask_user base via bbfa91c) with contenteditable composer
WIP checkpoint: both composers (chat + collab) to contenteditable+atomic chips on top
of lyx/017's ctx multi-composer; conductor send uses gaComposerText('collab'); --blue
-> --accent; flatpickr (PR#2). Re-merging latest main next.
2026-05-27 21:50:26 +08:00
yiqi-017 6fcdc7f2af [feat]:增加rename会话的功能 2026-05-27 21:36:07 +08:00
weaselkkkandCursor a860cf2d82 Merge branch 'feature/ask_user' into main
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-27 18:59:43 +08:00
dd3xp 7074c20f71 refactor(desktop): rename theme var --blue -> --accent; plain-icon sidebar toggles
- Rename the misleadingly-named --blue theme accent var to --accent (incl.
  --blue-bg/-soft -> --accent-bg/-soft) across styles.css + the applyTheme
  setter in app.js. Keep --blue* as back-compat aliases of --accent* so
  unmerged branches (e.g. PR#1) still render until they migrate.
- Sidebar / right-panel toggles: plain icon button when expanded (no bg/border);
  restore the edge-tab look (bg + border) only when collapsed.
- Bump asset cache-bust (styles.css v23 / app.js v30).
2026-05-27 18:46:35 +08:00
yiqi-017 4d31e1cd46 Merge branch 'feat/conductor' into main 2026-05-27 18:21:19 +08:00
yiqi-017 24ea45f028 [feat]:增加删除subagent的功能,增加跨域请求,增加subagent卡片点击展开的功能,并且把原本的collab.js全部放进去app.js里面 2026-05-27 18:19:38 +08:00
weaselkkk 6dfa75acd5 feat: update the style of agent questioning 2026-05-27 18:04:32 +08:00