17 Commits

Author SHA1 Message Date
lvjunjie-byte
6578916061 fix: 为飞书适配器的 HTTP 请求添加超时机制
问题:AdapterHttpClient 中的 HTTP 请求没有设置超时时间,
当服务器响应缓慢时,请求会无限期挂起,阻塞聊天队列,
导致飞书机器人看起来卡住了(电脑在运行,但飞书不回复)。

修复:
- 为所有 HTTP 方法添加 30 秒超时(AbortController)
- createSession、listRecentProjects、getGitInfo、getTasksForSession
- 为图片下载的 fetch 调用添加超时

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-26 15:10:14 +08:00
程序员阿江(Relakkes)
bfafd26fb6 fix: batch resolve 5 issues from Feishu bug tracker
- fix(desktop): Settings Agents/Skills page layout overflow at narrow widths
  Shift header grid breakpoint md→xl, summary cards sm→3col, add min-w-0/truncate

- fix(desktop): TabBar tab style — remove border-r separators, use bg-only active state
  Drop ::after indicator and inter-tab borders; active tab distinguished by surface bg

- feat(desktop): IM Adapters page — horizontal tabs with Feishu first, Telegram second
  Replace vertical stack with tablist; add ImTabButton with aria-selected + focus-visible

- fix(server): bundled IM session cwd resolves to / instead of selected project
  Root cause: preload.ts chdir(CALLER_DIR) inherits '/' from Tauri-spawned sidecar.
  Fix: pin CALLER_DIR and PWD to session workDir in conversationService spawn env.
  Add diagnostic logs at sessionService, ws/handler, and conversationService.

- fix(feishu): StreamingCard shows duplicate "thinking" indicators
  Merge static loading element into streaming_content; renderedText() controls state.

- test(adapters): add 5 ImageBlockWatcher edge-case unit tests (reset, relative path,
  multi-image chunk, malformed data URI)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 13:36:14 +08:00
程序员阿江(Relakkes)
80eaa8cc1e fix(adapters): tsconfig-strict types for Dirent and Lark image upload
- attachment-store.ts: pin Dirent<string>[] and pass `encoding: 'utf8'`
  so newer @types/node doesn't infer Dirent<NonSharedBuffer>
- feishu/media.ts: drop Readable.from(buffer) and pass Buffer directly
  to im.image.create / im.file.create — Lark SDK already accepts Buffer
  and the stream wrapper trips the stricter Buffer | ReadStream union
  used on the main branch's tsconfig

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 21:14:28 +08:00
程序员阿江(Relakkes)
6bcbbc547f fix(adapters): drop HEIC mime, align Telegram error text, inline extractText 2026-04-11 21:09:00 +08:00
程序员阿江(Relakkes)
ac89ec618c feat(adapters): add ImageBlockWatcher for streaming markdown image extraction 2026-04-11 21:08:30 +08:00
程序员阿江(Relakkes)
bf9b561cc7 fix(adapters): eliminate AttachmentStore collision race and orphan .part cleanup
Address two production issues in the AttachmentStore:
1. TOCTOU race in resolvePath() — concurrent downloads with same filename in
   the same millisecond could collide. Fixed by appending a 6-char random suffix
   to the timestamp-based path, ensuring millisecond-level collisions never occur.
2. Orphan .part files from crashed writes never cleaned up. Fixed by extending
   gc() to recognize .part files and clean them with a shorter grace period
   (10 minutes by default) rather than the normal retention window.

Added two test cases covering heavy collision pressure and .part cleanup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 21:08:30 +08:00
程序员阿江(Relakkes)
413437ced0 feat(adapters): add AttachmentStore for IM download staging 2026-04-11 15:33:56 +08:00
程序员阿江(Relakkes)
e2ea346754 feat(adapters): add attachment type and limit check module 2026-04-11 15:29:25 +08:00
程序员阿江(Relakkes)
63e5fb3a41 feat(adapters): extend WsBridge.sendUserMessage to carry attachments 2026-04-11 15:25:57 +08:00
程序员阿江(Relakkes)
4ccda92cfe chore(adapters): snapshot pre-attachment WIP (permission card v2, handler serialization, markdown style)
Carries forward ~800 lines of in-flight work that existed in the working
tree before the IM-attachment branch was cut. Kept as a single isolated
commit so later attachment work has a clean diff baseline and so this
WIP can be cherry-picked back to main on its own merits.

Contents:
- ws-bridge: per-chat handler chain serialization; sendPermissionResponse
  now accepts optional `rule: 'always'` for persistent permits
- feishu/index.ts: permission card rewritten to Schema 2.0 with icon,
  cross-dir warning, and ♾️ 永久允许 button; optimizeMarkdownForFeishu
  applied to streaming card
- feishu/markdown-style.ts: new Feishu-specific markdown downgrader
- tests: corresponding bun:test coverage

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 15:24:10 +08:00
程序员阿江(Relakkes)
635a966c3e fix(desktop): unblock rollout with reliable session and IM flows
This folds together the desktop-side fixes needed before broader rollout.
Session resume no longer deadlocks waiting on init, Mermaid and inline image
output render inside chat, task and sub-agent state stay visible during
execution, local build/release paths are safer, and Feishu/Telegram now expose
lightweight mobile commands (/help, /status, /clear) without adding a new
adapter-specific protocol.

Constraint: Desktop releases must publish updater artifacts from non-draft GitHub releases
Constraint: IM commands need short, phone-friendly responses and low operational complexity
Rejected: Add a dedicated IM command API surface | re-used existing slash commands and session/task REST endpoints to keep adapters thin
Rejected: Wait for task_update push events in WebUI | added low-risk polling because the current frontend ignores that event path
Confidence: medium
Scope-risk: broad
Reversibility: clean
Directive: Keep IM command replies terse and mobile-first, and merge local fallback slash commands when server-provided lists are partial
Tested: cd desktop && bun x vitest run src/components/chat/MermaidRenderer.test.tsx src/components/markdown/MarkdownRenderer.test.tsx
Tested: cd desktop && bun x vitest run src/components/chat/composerUtils.test.ts src/pages/ActiveSession.test.tsx src/stores/chatStore.test.ts
Tested: cd desktop && bun run lint
Tested: bun test src/server/__tests__/conversations.test.ts --test-name-pattern "SDK init arrives only after the first user turn" --timeout 60000
Tested: cd adapters && bun test common/ feishu/ telegram/
Tested: cd adapters && bunx tsc --noEmit
Not-tested: Full GitHub Actions release run on all three desktop platforms
Not-tested: Local DMG packaging end-to-end on Apple Silicon
Not-tested: Real Feishu/Telegram device sessions against a live adapter process
2026-04-10 16:41:59 +08:00
程序员阿江(Relakkes)
41fc58d73a feat(adapters): add /new <project> quick switch and unify project selection
- Add matchProject() to http-client for fuzzy project matching by
  index or name
- Extract startNewSession() in both adapters to share reset + match +
  create logic
- Project selection replies now go through startNewSession(), creating
  a clean new session instead of continuing the old one
- Support: /new 2 (by index), /new backend (by name), /new (default)
- Add usage hint in /projects list output

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 21:25:23 +08:00
程序员阿江(Relakkes)
824b1967ff fix(adapters): fix IM message delivery issues and improve UX
- Fix WebSocket race condition: wait for connection to open before
  sending first message, preventing silent message loss after pairing
  or project selection
- Fix response text appearing above tool calls: finalize placeholder
  before tool_use blocks so post-tool text gets a new message
- Remove noisy tool_use and tool_result messages from IM output;
  thinking indicator is preserved, details visible in Desktop
- Fix /new command using default project dir instead of always showing
  project picker
- Fix duplicate projects in list by deduping on realPath instead of
  projectPath
- Improve formatToolUse with human-readable summaries for common tools
- Add send failure feedback to users

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 20:40:07 +08:00
程序员阿江(Relakkes)
158f2de13e fix(security): add rate limiting, default-closed mode, extract isAllowedUser
- Rate limit: max 5 failed pairing attempts per user per 5 minutes
- Default closed: reject all users when no allowedUsers/pairedUsers configured
- Extract isAllowedUser() to common/pairing.ts to eliminate duplication

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 20:51:30 +08:00
程序员阿江(Relakkes)
4bcac9d25f feat(pairing): implement core pairing logic module
Add adapters/common/pairing.ts with generatePairingCode(), isPaired(),
and tryPair() — one-time-use 6-char code flow with atomic config writes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 20:07:44 +08:00
程序员阿江(Relakkes)
88e7e14598 feat(pairing): extend type definitions with pairing and pairedUsers fields
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 20:06:37 +08:00
程序员阿江(Relakkes)
82e6e27687 feat: add IM adapter integration (Telegram + Feishu) with web settings UI
Implement IM adapters allowing users to chat with Claude Code from Telegram
and Feishu/Lark. Includes persistent session management (chatId→sessionId
mapping), project selection via /projects command, and a web UI settings page
for configuring bot tokens, allowed users, and default project directory.

Key changes:
- adapters/: Telegram and Feishu adapter scripts with shared common modules
  (WsBridge, MessageBuffer, SessionStore, HttpClient, config, formatting)
- Backend: adapterService + REST API (GET/PUT /api/adapters) with secret masking
- Frontend: AdapterSettings page in Settings tab with i18n support
- DirectoryPicker: use React Portal for dropdown to fix overflow clipping

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 19:38:51 +08:00