7418 and Claude Opus 4.6
19aba25c8f
feat: assistant workspace — persistent AI personality & memory via Markdown files ( #165 )
...
Add "Assistant Workspace" feature that lets users designate a directory
(e.g. Obsidian vault) containing 4 Markdown files (soul.md, user.md,
memory.md, claude.md) to define AI personality, user profile, long-term
memory, and execution rules. These files are automatically injected into
the system prompt for assistant project sessions.
Core library (src/lib/assistant-workspace.ts):
- Workspace validation, initialization with template files
- File loading with 8000-char truncation, XML prompt assembly (40k limit)
- State management via .assistant/state.json
- Directory docs generation (README.ai.md + PATH.ai.md)
- Case-insensitive file name fallback (soul.md → SOUL.md)
System prompt injection (src/app/api/chat/route.ts):
- Scoped to sessions where working_directory === workspace path
- Workspace prompt prepended before session-level system prompt
- Onboarding/check-in instructions injected as <assistant-project-task>
- autoTrigger flag skips user message save and title update
Chat-based onboarding (10 questions) & daily check-in (3 questions):
- AI conducts conversation, outputs structured completion code blocks
- Frontend detects onboarding-complete/checkin-complete blocks
- Backend calls Claude API to generate file content from answers
- Fallback to raw answers if API call fails
Auto-trigger pipeline:
- Mount trigger (500ms delay) + focus fallback in MessageInput
- assistantTriggerFiredRef prevents duplicate triggers per mount
- hookTriggeredSessionId in state.json prevents cross-reload duplicates
- Daily check-in only triggers in the most recent workspace session
- hookTriggeredSessionId cleared via __clear__ sentinel after completion
API endpoints:
- GET/PUT /api/settings/workspace — path CRUD + file status
- POST /api/workspace/session — create (onboarding) or reuse (check-in)
- POST /api/workspace/onboarding — AI-generate soul.md + user.md
- POST /api/workspace/checkin — AI-update memory.md + user.md
- POST /api/workspace/hook-triggered — set/clear trigger guard
- GET /api/workspace/latest-session — latest session lookup
- POST /api/workspace/docs — refresh directory documentation
UI:
- Settings "Assistant" tab with workspace path, file status, controls
- Violet badge on workspace project group in ChatListPanel
- useAssistantWorkspace hook for state queries
Also includes:
- 102 passing tests (16 new regression tests for workspace logic)
- i18n keys for en.ts and zh.ts
- Handover documentation and execution plan
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-06 20:31:42 +08:00
Wujie Li
3f19290c8d
fix: preserve paragraph breaks between text blocks in bridge responses ( #144 )
...
When Claude's response includes tool calls (Read, Edit, Bash, etc.),
the response text is split into multiple content blocks — one before
each tool call and one after. These blocks were joined with an empty
string (.join('')), causing all paragraphs to concatenate without
any spacing in the final Telegram message.
Changed .join('') to .join('\n\n') so paragraph breaks between text
blocks are preserved, matching how they appear in the desktop UI.
2026-03-05 11:00:06 +08:00
jasonjaclyn2017 and Claude Opus 4.6
a1bde18cd1
feat: add View Plan modal and feedback textbox to plan approval UI ( #164 )
...
* feat: add "View Plan" button with fullscreen modal to ExitPlanMode UI
When Claude writes a plan in plan mode, the plan content is written to a
file on disk but the ExitPlanMode UI only shows Approve/Reject buttons —
the user never sees the actual plan without manually finding the file.
Add a "View Plan" button that opens a fullscreen Dialog modal showing
the plan content rendered as markdown. The plan content is extracted from
the tool uses array (the Write tool's input for the plan file), so no
new API endpoints are needed.
Changes in StreamingMessage.tsx:
- extractPlanContent(): walks toolUses backwards to find the last Write
to a plans/*.md file and returns its content
- ExitPlanModeUI: accepts toolUses prop, renders "View Plan" button
(hidden if no plan content found), opens Radix Dialog modal with
MessageResponse markdown renderer
- Modal is 80vh tall, max-w-4xl, scrollable, with Close button
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
* feat: add "Do this instead" feedback textbox to plan approval UI
When rejecting a plan, users can now type feedback and click "Do this
instead" (or press Enter) to send a custom deny message to the SDK.
This matches the Claude Code CLI behavior where users can provide
alternative instructions when rejecting a plan.
Previously, the deny message was hardcoded to "User denied permission"
— the API already supported custom messages but the client never sent
them.
Changes:
- StreamingMessage.tsx: add feedback textbox + "Do this instead" button
to ExitPlanModeUI, wire onDenyWithMessage callback
- ChatView.tsx: pass denyMessage through handlePermissionResponse
- MessageList.tsx: update onPermissionResponse type signature
- stream-session-manager.ts: add denyMessage param to
respondToPermission(), use it in the deny decision body
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
* fix: fetch plan content from disk so View Plan always shows latest version
Previously extractPlanContent read the Write tool's input.content, which
showed stale content when Claude later edited the plan via the Edit tool.
Now extractPlanFilePath finds the plan file path (matching both Write and
Edit tools, with Windows backslash support), and the View Plan button
fetches the file from disk on each click via /api/files/preview.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-05 11:00:02 +08:00
jasonjaclyn2017 and Claude Opus 4.6
a906172807
fix: handle SDK keep_alive messages to prevent idle timeout during long operations ( #163 )
...
The stream idle timer (330s) fires during long-running Claude Code tool
executions because the SDK's keep_alive heartbeat messages are silently
dropped. This causes a false "Stream idle timeout" error even though
Claude is still actively working.
Root cause: claude-client.ts only handles 6 SDK message types in its
switch statement and has no default case, so keep_alive messages from
the SDK are never forwarded to the frontend. The idle timer in
stream-session-manager.ts never gets reset by markActive().
Fix: thread keep_alive through the existing 3-layer event pipeline:
- claude-client.ts: forward keep_alive as SSE event (via default case)
- useSSEStream.ts: add onKeepAlive callback to SSECallbacks interface
- stream-session-manager.ts: call markActive() on keep_alive to reset
the idle timer
No visible UI change — keep_alive only resets the timer silently.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-05 10:59:43 +08:00
315aac0f04
fix: sanitize __NEXT_PRIVATE_* env vars from child processes ( #161 )
...
* fix: preserve paragraph breaks between text blocks in bridge responses
When Claude's response includes tool calls (Read, Edit, Bash, etc.),
the response text is split into multiple content blocks — one before
each tool call and one after. These blocks were joined with an empty
string (.join('')), causing all paragraphs to concatenate without
any spacing in the final Telegram message.
Changed .join('') to .join('\n\n') so paragraph breaks between text
blocks are preserved, matching how they appear in the desktop UI.
* fix: sanitize __NEXT_PRIVATE_* env vars from child processes
The bundled Next.js standalone server sets __NEXT_PRIVATE_STANDALONE_CONFIG
and __NEXT_PRIVATE_ORIGIN in process.env at runtime. These leak into every
child process spawned by the Electron main process (Claude Code CLI,
node version checks, package installs, etc.), which in turn pollutes
tmux/terminal sessions.
When other Next.js projects detect __NEXT_PRIVATE_STANDALONE_CONFIG in their
environment, they skip normal next.config loading and use CodePilot's baked-in
config instead — silently breaking builds and dev servers system-wide.
Fix: strip all __NEXT_PRIVATE_* variables when constructing env objects for
child processes. The standalone server.js already sets these internally, so
they don't need to be passed from the parent.
Generated with [Claude Code](https://claude.ai/code )
via [Happy](https://happy.engineering )
Co-Authored-By: Claude <noreply@anthropic.com >
Co-Authored-By: Happy <yesreply@happy.engineering >
---------
Co-authored-by: Claude <noreply@anthropic.com >
Co-authored-by: Happy <yesreply@happy.engineering >
2026-03-05 10:59:39 +08:00
7418 and Claude Opus 4.6
113e15e2f4
feat: Discord bridge adapter — 完整实现 Discord 作为第三个桥接渠道
...
新增文件:
- discord-adapter.ts: 基于 discord.js v14 的适配器,支持 DM/频道消息、
按钮交互、流式预览(edit-based)、@提及过滤(兼容角色 mention)、
图片附件下载、!→/ 命令归一化、消息去重、typing indicator
- markdown/discord.ts: Discord 2000 字符分段,代码块围栏自动平衡
- API routes: settings CRUD(Token 掩码)+ verify(Discord REST 验证)
- DiscordBridgeSection.tsx: 设置 UI(凭据、授权、服务器策略、配置指南含 ID 获取方法)
- discord-bridge.test.ts: 22 项单元测试(chunking/auth/command/HTML 转换)
修改文件:
- bridge-manager.ts: Discord 分段投递 + channel-aware stream config
(Discord 默认 1500ms/40chars/1900max vs Telegram 700ms/20/3900)
- BridgeLayout/BridgeSection: Discord 渠道开关和侧栏入口
- bridge/settings/route.ts: 新增 14 个 Discord 设置键
- next.config.ts: serverExternalPackages 添加 discord.js/zlib-sync
- i18n: 中英文完整翻译(30+ keys)
- docs/handover/bridge-system.md: Discord 架构文档
依赖:discord.js ^14.18.0, zlib-sync ^0.1.9
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-04 23:32:46 +08:00
7418 and Claude Opus 4.6
538cc1b7fd
docs: 工程质量保障体系执行计划文档
...
- 新建 completed/engineering-quality-assurance.md:记录 Harness Engineering
全部 5 个已完成 Phase 和 4 个未实现 Phase 的详细内容
- 更新 exec-plans/README.md 索引
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-04 21:08:49 +08:00
7418 and Claude Opus 4.6
935e3d030c
fix: i18n 品牌名修正 — Claude → CodePilot
...
- en.ts / zh.ts: messageList.claudeChat 和 emptyDescription 中的
"Claude" 改为 "CodePilot",与应用品牌一致
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-04 21:00:52 +08:00
7418 and Claude Opus 4.6
a8e1bca9d3
chore: bump version to v0.25.1
...
工程化改进版本:
- 激活验证闭环(pre-commit hook + CI gate + npm test scripts)
- CLAUDE.md 改造 + ARCHITECTURE.md 架构导航
- 执行计划体系 + 技术债务追踪
- chrome-devtools MCP 集成 + UI 验证规则
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-04 19:54:53 +08:00
7418 and Claude Opus 4.6
a7104aa4eb
chore: 集成 chrome-devtools MCP + UI 验证规则
...
.mcp.json(新建):
- 添加 chrome-devtools MCP server(stdio 模式,npx chrome-devtools-mcp@latest)
- 签入仓库使团队成员 clone 后自动启用
CLAUDE.md:
- 新增"UI 改动必须用 CDP 验证"规则:
修改组件/样式/布局后,通过 chrome-devtools MCP 截图确认渲染正确、
检查 console 无报错、模拟交互验证、响应式布局用 device emulation 验证
目的:建立 UI 改动的自动化视觉验证闭环,
AI 修改前端代码后自动启动浏览器截图检查,而非仅靠 typecheck 判断正确性。
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-04 19:50:18 +08:00
7418 and Claude Opus 4.6
62dbecd5dc
docs: 执行计划体系 + 技术债务追踪 + CLAUDE.md 执行计划规则
...
docs/exec-plans/(新建目录):
- README.md — 执行计划规范、模板、何时需要写执行计划
- active/context-storage-migration.md — 从 research/ 迁移,标注 Phase 0-3 进度状态
(Phase 0 部分完成:sdk_cwd 上线;projects 表和 canUpdateSdkCwd 未实现)
- tech-debt-tracker.md — 4 项已知技术债务(ESLint 存量 error、内存态注册表、
固定 50 条 fallback、Phase 0 剩余项)
CLAUDE.md:
- 新增"执行计划"区块:中大型功能必须先写执行计划再开工
- 文档区块增加 exec-plans/ 索引
ARCHITECTURE.md:
- 关键文档索引增加执行计划和技术债务条目
docs/research/README.md:
- context-storage-migration-plan 条目增加交叉引用指向执行文档
docs/CLAUDE.md:
- 增加 exec-plans/ 目录说明和文档分类规则
目的:确保 AI 后续会话能自动遵循执行计划流程,
读取进度状态而不需要重新口头解释历史。
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-04 19:44:12 +08:00
7418 and Claude Opus 4.6
e0c38af4fa
docs: CLAUDE.md 改造为路由层 + 新建 ARCHITECTURE.md
...
CLAUDE.md:
- 顶部增加指向 ARCHITECTURE.md 的导航
- 新增"改动自查"区块(i18n / 数据库 / 类型 / 文档四项检查)
- 文档区块增加 ARCHITECTURE.md 索引
- 保持所有原有规则不变,仅重组结构使其更清晰
ARCHITECTURE.md(新建,~120 行):
- 技术栈概述(Electron 40 + Next.js 16 + SQLite)
- 目录结构地图(src/ 下所有一级目录及关键文件职责)
- 数据流图(用户输入 → API → SDK → SSE → 渲染 → 持久化)
- Bridge 数据流图(IM → Adapter → Router → Engine → Delivery → IM)
- 数据库 12 张表索引
- Bridge 子系统核心组件说明
- 新增功能标准触及点清单(类型/数据库/API/页面/组件/Hook/i18n/Bridge)
- 关键文档索引(handover + research)
- 技术栈速查表
目的:减少每次 Claude Code 会话的探索成本,直接跳转到正确位置。
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-04 19:38:52 +08:00
7418 and Claude Opus 4.6
99c4931b12
chore: 激活验证闭环 — pre-commit hook + CI gate + npm test scripts
...
三层质量保障闭环:
package.json:
- 新增 typecheck / test:unit / test:smoke / test:e2e / test / prepare 脚本
- 新增 lint-staged 配置(仅对暂存 .ts/.tsx 文件运行 eslint --fix)
- 新增 devDependencies: husky, lint-staged, tsx
.husky/pre-commit:
- 依次执行 lint-staged → tsc --noEmit → 单元测试
- 任一步骤失败即阻止提交
src/__tests__/e2e/smoke.spec.ts:
- 5 个 Playwright @smoke 测试覆盖核心路由 (/, /chat, /plugins, /plugins/mcp, /settings)
- 检查 HTTP 状态、Next.js 错误覆盖层、标题、console 错误
- 复用已有 helpers (goToChat, goToPlugins, goToMCP, goToSettings, collectConsoleErrors, filterCriticalErrors)
.github/workflows/build.yml:
- 新增 lint-test job (ubuntu-latest): lint → typecheck → unit tests
- 新增 pull_request 触发器
- 三个 build job 添加 needs: [lint-test],lint-test 失败则不构建
- lint 步骤暂设 continue-on-error(存量 4 个 lint error 待修复)
CLAUDE.md:
- 新增"自检命令"区块,说明 test / test:smoke / test:e2e 用途
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-04 19:33:01 +08:00
7418 and Claude Opus 4.6
243724a765
feat: 飞书(Feishu/Lark)Bridge 适配器 + 发布 v0.25.0
...
新增飞书 IM 通道,通过 @larksuiteoapi/node-sdk WSClient 接收消息、REST Client 发送回复。
适配器核心 (feishu-adapter.ts):
- WSClient 长连接接收 im.message.receive_v1 事件
- 消息去重 (message_id LRU 1000)、授权校验、群聊策略 (open/allowlist/disabled)
- @提及检测 (bot open_id/user_id/union_id 匹配)
- 图片/文件/音频/视频/富文本(post) 下载 → base64 FileAttachment
- Typing 指示器 (Openclaw 方案: emoji reaction)
- /perm 文本命令处理权限审批
渲染策略 (markdown/feishu.ts):
- 代码块/表格 → schema 2.0 interactive card (markdown 元素)
- 纯文本 → post (md tag), 支持粗体/斜体/行内代码/链接
- 权限卡片 → schema 2.0 card + /perm 文本命令 (无按钮, 见下方决策)
- 每层降级: card → post → text
关键决策 — 权限交互无按钮:
- 飞书 card.action.trigger 回调需 HTTP webhook, WSClient 不支持
- schema 2.0 不支持 action 标签 (错误码 200861)
- schema 1.0 按钮可渲染但点击报 200340 (无 webhook 端点)
- Openclaw 用 http.createServer + Lark.adaptDefault 解决, CodePilot 桌面端无公网端点
- 最终方案: 格式化卡片 + /perm 文本命令, 用户复制发送即可审批
其他变更:
- permission-broker.ts: permissionRequestId 去重 (30s TTL)
- telegram-bot.ts: bridge 模式互斥 (globalThis 标志)
- bridge-manager.ts: 飞书渲染分发 (deliverResponse feishu 分支)
- UI: FeishuBridgeSection 设置页 + 侧边栏入口 + 通道开关
- i18n: 中英文飞书配置文案
- 交接文档: bridge-system.md 更新飞书架构、数据流、6 项设计决策
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-04 19:03:13 +08:00
7418 and Claude Opus 4.6
b1a043a995
feat: Telegram 流式预览(sendMessageDraft)+ 出站渲染解耦 + 投递容错
...
Bridge 新增"边生成边显示"能力,利用 Telegram Bot API 9.5 的
sendMessageDraft 在私聊中以草稿形式流式展示 Claude 生成进度。
架构上抽象为通道级可选能力,便于后续扩展到其他 IM。
types.ts
- 新增 PreviewCapabilities、StreamingPreviewState 接口
channel-adapter.ts
- BaseChannelAdapter 新增三个可选方法:
getPreviewCapabilities / sendPreview / endPreview
- sendPreview 返回 'sent'|'skip'|'degrade' 三态,
区分瞬时失败(跳过)和永久失败(降级)
telegram-utils.ts
- 新增 sendMessageDraft() API 封装(plain text,截断到 4096)
telegram-adapter.ts
- 实现 getPreviewCapabilities: 开关检查 + 私聊/群聊检测 + 降级状态
- 实现 sendPreview: 调 sendMessageDraft,400/404 永久降级,429 仅跳过
- 实现 endPreview: 空操作
- stop() 清空 previewDegraded Set
conversation-engine.ts
- 新增 OnPartialText 回调类型
- processMessage / consumeStream 透传 onPartialText 参数
- 使用独立 previewText 变量(只累积、不因 tool_use 清零),
避免预览文本在工具调用后回退/抖动
bridge-manager.ts
- 流式预览状态机:generateDraftId / getStreamConfig / flushPreview
节流闭包(间隔+最小增量+trailing-edge timer),finally 清理
- flushPreview 仅在 'degrade' 时降级,'skip'/网络错误不降级
- 新增 deliverResponse() 按 channelType 分发渲染:
Telegram → markdownToTelegramChunks + deliverRendered
其他 IM → deliver() 纯文本(内部自动分块)
解除 handleMessage 对 Telegram 渲染的硬编码依赖
delivery-layer.ts
- deliverRendered: chunk 失败后继续投递剩余 chunk(不中断),
追发截断提示通知用户,返回 ok:false 标识不完整投递
- deliver: 保持原有 fail-fast 行为(短消息无需跳过)
route.ts (bridge/settings)
- BRIDGE_SETTING_KEYS 白名单追加 5 个流式配置项
docs/handover/bridge-system.md
- 更新目录结构、数据流、设计决策(#12 流式预览)、设置项表
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-03 23:20:47 +08:00
7418
6dfe23a9a9
fix: 修复百炼 API key 配置并发布 v0.23.1
2026-03-03 16:36:10 +08:00
7418 and Claude Sonnet 4.6
5413eb55ba
refactor: 简化 macOS 构建 — 只签名不公证,禁用原生热更新
...
CI (.github/workflows/build.yml):
- 删除 mac_notarize 输入、notarization strategy/credentials 步骤
- 双架构回归单步构建,统一 -c.mac.notarize=false
- 证书缺失时硬失败,不 fallback ad-hoc
- 上传产物移除 blockmap / latest-mac.yml
- release 收集资产移除 blockmap / yml 元数据
electron-builder.yml:
- mac.notarize 固定为 false
Electron 主进程 (main.ts):
- 移除 initAutoUpdater / setUpdaterWindow 调用和 import
Preload (preload.ts):
- 移除 updater bridge,不再暴露 electronAPI.updater
Updater (updater.ts):
- 恢复为 no-op stub
前端 AppShell 无需改动 — isNativeUpdater 运行时检测 updater 不存在,
自动走 /api/app/updates 浏览器模式(全量下载链接)。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-03 13:27:35 +08:00
7418 and Claude Sonnet 4.6
5629da9571
fix: arm64 打包脚本改用 if/else 分支替代 EXTRA_ARGS 数组
...
bash 数组展开在 GitHub Actions 中不稳定,
改为 NOTARIZE 变量 + if/else 直接调用不同命令行。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-03 11:45:10 +08:00
7418 and Claude Sonnet 4.6
db86644c7e
feat: macOS 双架构分离构建 — x64 只签名,arm64 签名+条件公证
...
CI:
- 拆分为 x64 和 arm64 两个独立构建步骤
- x64: 签名但不公证(-c.mac.notarize=false),timeout 15min
- arm64: 签名 + 按版本号条件公证(vX.Y.0 公证,vX.Y.Z 只签名),timeout 35min
- 先跑 x64,stash 产物后跑 arm64,确保 latest-mac.yml 来自 arm64
Electron:
- electron/main.ts: darwin+x64 跳过 initAutoUpdater
- electron/preload.ts: darwin+x64 不暴露 updater bridge
- 前端 AppShell 已有运行时检测(!!window.electronAPI?.updater),
x64 自动 fallback 到 browser 模式更新检查
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-03 11:35:50 +08:00
7418 and Claude Sonnet 4.6
2c76b04729
feat: macOS 公证策略 — 大版本公证,小版本只签名
...
- workflow_dispatch 新增 mac_notarize 输入(auto/on/off)
- auto 模式:vX.Y.0 签名+公证,vX.Y.Z(Z>0) 只签名不公证
- 打包超时调整为 35 分钟,notarize=false 时传 -c.mac.notarize=false
- 凭证校验步骤仅在需要公证时执行
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-03 11:17:28 +08:00
7418 and Claude Sonnet 4.6
0ac424f408
fix: macOS 打包步骤添加 25 分钟超时限制
...
避免 notarization 排队无限等待消耗 CI 额度。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-03 11:08:37 +08:00
7418 and Claude Sonnet 4.6
f50a8879db
fix: macOS 打包步骤添加 notarization 重试(最多 3 次)
...
Apple notarization 服务偶发网络超时,加递增间隔重试(60s/120s)。
同时启用 DEBUG=electron-notarize* 方便排查 notarization 日志。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-03 09:56:42 +08:00
7418 and Claude Sonnet 4.6
c24dedcffe
fix: CI 添加 notarization 凭证预校验步骤
...
在打包前用 xcrun notarytool history 验证 APPLE_ID / APP_SPECIFIC_PASSWORD / TEAM_ID
凭证组合是否有效,提前暴露凭证配置问题。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-03 01:30:09 +08:00
7418 and Claude Sonnet 4.6
8749adaeb9
fix: CI 证书解码去除换行 + openssl 预校验
...
printf + tr -d 去除 base64 中可能的 \r\n,
openssl pkcs12 -noout 在签名前验证 .p12 格式和密码正确。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-03 01:14:42 +08:00
7418 and Claude Sonnet 4.6
261d17c059
fix: CI 解码 base64 证书为 .p12 文件后传给 CSC_LINK
...
electron-builder 把 base64 字符串当文件路径解析导致构建失败。
改为先 base64 --decode 写入 /tmp/cert.p12,CSC_LINK 指向文件路径。
同时加 HAS_CERT 环境变量控制签名/验证步骤的条件执行。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-03 00:57:57 +08:00
7418 and Claude Sonnet 4.6
0e38e4460e
feat: macOS Developer ID 签名 + notarization + 原生热更新
...
签名 & 公证:
- build/entitlements.mac.plist, build/entitlements.mac.inherit.plist — Electron hardened runtime 所需权限(JIT、unsigned memory、disable library validation)
- electron-builder.yml — 启用 hardenedRuntime、entitlements、notarize: true
- scripts/after-sign.js — 环境变量 + codesign -d 双重检测,有 Developer ID 时跳过 ad-hoc;无证书时 fallback ad-hoc
- .github/workflows/build.yml — 映射签名 secrets(MAC_CERT_P12_BASE64 等),验证步骤断言 Developer ID Authority + TeamIdentifier,遍历双架构 .app
原生热更新:
- electron/updater.ts — 从 no-op 重写为完整 electron-updater 实现(autoDownload:false, IPC handlers, 启动 10s 延迟检查)
- electron/preload.ts — 恢复 updater IPC bridge
- src/components/layout/AppShell.tsx — 运行时检测 native updater,useEffect 监听 updater:status 事件,native 优先 + browser fallback
其他:
- README_CN.md — 更新自动更新功能描述
- package.json — 版本号升至 0.23.0
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-03 00:46:51 +08:00
7418 and Claude Opus 4.6
ddb2c00a8c
fix: Skills API 增加项目级 .claude/skills 扫描
...
列表接口 (route.ts):
- 新增 getProjectSkillsDir + scanProjectSkills 扫描 .claude/skills/*/SKILL.md
- 解析 YAML front matter 取 name/description,source 为 "project"
- 与 project commands 去重(commands 优先)
按名查找接口 ([name]/route.ts):
- findSkillFile 查找链路扩展:project commands → project skills → global → installed
- 支持目录名直接匹配和 front matter name 匹配
- GET 对 SKILL.md 从 front matter 取 description
- PUT 增加 cwd 参数支持
修复与 Agent SDK 的目录约定不一致问题:SDK 会加载项目级
.claude/skills,但本项目 API 之前只扫 commands 目录和用户级 skills。
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-02 17:30:57 +08:00
7418 and Claude Opus 4.6
5dda2ea1e3
fix: CI release 步骤处理含空格的文件名
...
Windows 安装包文件名 "CodePilot Setup x.x.x.exe" 含空格,
$FILES 变量展开时被 bash word splitting 拆成多个参数导致
gh release create 找不到文件。改用 bash 数组 + "${FILES[@]}"
安全展开。
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-02 14:55:51 +08:00
7418 and Claude Opus 4.6
38e7c96daa
feat: Telegram Bridge 出站消息 Markdown 渲染
...
新增三层 Markdown → Telegram HTML 渲染管线:
markdown/ir.ts — markdown-it 解析 Markdown 为中间表示 (MarkdownIR)
- 支持 bold/italic/strikethrough/code/code_block/blockquote/links/lists/headings/tables/hr
- 表格使用 code-block 模式渲染为 ASCII 表格(<pre> 保留对齐)
- HTML 内联 <br> 标签转换为换行符
markdown/render.ts — 通用标记渲染器
- boundary tracking + LIFO stack 处理嵌套样式
markdown/telegram.ts — Telegram 专用渲染器
- 样式映射到 Telegram HTML 标签 (b/i/s/code/pre+code/blockquote/a)
- 文件引用保护:README.md/main.go 等不被误识别为 URL
- render-first 分片:按渲染后 HTML 长度分片,超限时按比例重分割
delivery-layer.ts — 新增 deliverRendered() 接收预渲染 chunks
- HTML + plain text 双通道,解析失败自动降级纯文本
- sendWithRetry 支持 plainFallback 参数
bridge-manager.ts — Claude 回复改用 markdownToTelegramChunks + deliverRendered
- 命令响应和错误消息保持 escapeHtml + deliver
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-02 14:38:12 +08:00
7418 and Claude Opus 4.6
8526b58d59
docs: 更新 bridge 交接文档 — 图片接收能力
...
- 目录结构增加 telegram-media.ts
- 数据流图补充图片/相册处理路径
- 设计决策 #2 补充连续水位推进机制
- 新增决策 #9(图片接收)和 #10(DB 格式统一)
- 设置项表增加 image_enabled 和 max_image_size
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-02 13:06:48 +08:00
7418 and Claude Opus 4.6
69d33df5b6
fix: Bridge 图片消息在桌面端聊天记录中回显
...
conversation-engine 保存用户消息时,复用桌面端 chat route 的存储格式:
- 将 base64 图片写入 .codepilot-uploads/ 目录
- 用 <!--files:[{id,name,type,size,filePath}]--> 格式嵌入消息 content
- 桌面 UI 的 MessageItem.parseMessageFiles() 可直接解析并通过
FileAttachmentDisplay + /api/uploads 渲染图片
将 getSession() 调用提前到 addMessage 之前,确保 workingDirectory 可用。
写入失败时降级为 [N image(s) attached] 文本指示。
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-02 12:58:50 +08:00
7418 and Claude Opus 4.6
887870c343
fix: Telegram 图片接收 — offset 安全、caption 兜底、拒绝通知
...
P1a: caption-only 消息丢失
- poll loop 文本提取统一为 m.text ?? m.caption ?? ''
- 修复 image_enabled=false 时带 caption 的图片消息被跳过的回归
P1b: offset 越序风险
- markUpdateProcessed 改为连续水位推进(contiguous walk),
不再直接跳到 updateId+1,避免越过尚未 flush 的相册 ID
- flushMediaGroup 成功入队后预注册所有 buffered ID 到 recentUpdateIds,
保证 ack 时水位能连续推过整个相册
P2: 图片拒绝通知
- telegram-media: 统一返回 MediaDownloadResult { attachment, rejected, rejectedMessage }
reject code 覆盖 too_large | unsupported_type | download_failed
所有超限检查点(file_size/content-length/buffer)均返回可读文案
- telegram-adapter: processSingleImageMessage/flushMediaGroup 收集拒绝结果后
直接通过 this.send() 发送通知到 Telegram,禁止静默丢弃
P3: 清理 lint warning
- 移除未使用的 escapeHtml import、QueueEntry interface
- 移除 downloadFileById 未使用的 expectedSize 参数
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-02 12:53:55 +08:00
7418 and Claude Opus 4.6
570d26de3a
feat: Telegram Bridge 图片接收能力
...
新增 telegram-media.ts 模块,处理 Telegram 图片下载与 base64 转换:
- selectOptimalPhoto: 选最优尺寸(长边 ≥ 1568px 的最小版本)
- downloadPhoto/downloadDocumentImage: getFile API → 下载 → base64,3 次重试 + 指数退避
- document 类型图片超 20MB 预检拒绝,提示用户按照片发送
- kill switch: bridge_telegram_image_enabled 设置项
扩展 telegram-adapter.ts poll loop:
- TelegramUpdate 类型增加 caption/photo/document/media_group_id
- 单图消息直接下载入队
- 相册消息 500ms 防抖合并后批量下载,构建单条 InboundMessage
- offset 安全:相册使用 max(updateIds) 保证不丢消息
透传 attachments 至 Claude vision pipeline:
- types.ts: InboundMessage 新增 attachments 可选字段
- conversation-engine.ts: processMessage 新增 files 参数,传入 streamClaude
- bridge-manager.ts: 允许纯图片消息通过,透传 attachments
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-02 12:37:13 +08:00
7418 and Claude Opus 4.6
c9f1b62809
fix: 模型切换串台 + 发送消息后滚动不到底部
...
1. page.tsx — loadSession 加 cancelled 竞态守卫,快速切换会话时
丢弃过期的 fetch 结果,防止旧会话的 model/provider 覆盖新会话
2. ChatView.tsx — 去掉 if(modelName)/if(providerId) 守卫,改为
无条件同步 props,空值走 localStorage → default fallback 链
3. ChatListPanel.tsx + types + route.ts + db.ts — 三个创建会话入口
(handleFolderSelect/handleNewChat/handleCreateSessionInProject)
统一从 localStorage 读取并传递 model + provider_id,DB 层写入
4. MessageList.tsx — ScrollOnStream 增加 messageCount prop,
消息数增加时立即 scrollToBottom,覆盖乐观插入和 assistant 落地
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-02 12:01:10 +08:00
7418 and Claude Opus 4.6
b5e5645702
fix: CI 产物丢失 — 改为 release job 统一上传
...
之前各 build job 用 --publish always 并发上传到同一个 draft release,
存在竞争条件:后完成的 job overwrite 时先删后传,如果 release job
在上传未完成时执行 --draft=false,已删除的产物就丢了(DMG 丢失)。
改为:
- 各 build job 用 --publish never,产物通过 upload-artifact 上传
- release job 用 download-artifact 收集所有产物
- gh release create 一次性创建 release 并上传全部文件
同时将 .claude/rules/ 内容合回 CLAUDE.md(rules 文件与 CLAUDE.md
优先级相同,都会全量加载,拆分不减少上下文消耗)。
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-01 23:40:31 +08:00
7418 and Claude Opus 4.6
6a148f2dba
chore: bump v0.21.2
...
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-01 22:59:19 +08:00
7418 and Claude Opus 4.6
ead5cfcf8b
refactor: 精简 CLAUDE.md + 分层上下文管理
...
根 CLAUDE.md 从 80 行压缩到 15 行,详细规则拆分到按需加载位置:
- .claude/rules/development.md — 开发规则、测试要求、commit 规范
- .claude/rules/release.md — 发版流程、纪律、Release Notes 格式、构建说明
- docs/CLAUDE.md — docs 目录导航,要求检索前先读子目录 README
- src/lib/bridge/CLAUDE.md — bridge 模块关键约定(runAdapterLoop 时序、
bridgeModeActive 互斥、offset 安全水位、adapter 扩展方式)
目的:减少每次会话的固定上下文消耗,非相关模块的文档不加载到上下文。
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-01 22:59:00 +08:00
7418 and Claude Opus 4.6
d9c4ad2c95
fix: 切换聊天后模型选择不保持
...
两个问题:
1. 用户选择模型只写 localStorage,不写 DB。切换聊天回来后从 DB
读到空值,模型回退到默认值
2. ChatView 的 useState 只用初始值,后续 modelName prop 异步更新
不会同步到 currentModel state
修复:
- handleProviderModelChange 选择模型时立即 PATCH 到 DB
- PATCH /api/chat/sessions/:id 新增 model + provider_id 字段支持
- ChatView 添加 useEffect 同步 modelName/providerId prop 变化
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-01 22:55:36 +08:00
7418 and Claude Opus 4.6
7e45448860
fix: 滚动条不在底部时发送消息看不到 AI 输出
...
use-stick-to-bottom 库仅在 isAtBottom=true 时跟随新内容自动滚动。
用户滚动上去后发送消息,流式内容渲染在视口下方不可见。
新增 ScrollOnStream 组件,监听 isStreaming 从 false→true 的变化,
强制调用 scrollToBottom(),确保流式输出开始时自动跳到底部。
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-01 22:49:35 +08:00
7418 and Claude Opus 4.6
6209c865fd
refactor: 整理 docs 目录结构
...
- docs/handover/ — 交接文档(架构、设计决策)
- docs/research/ — 调研文档(技术方案、可行性分析)
- 各目录添加 README.md 索引,要求 AI 增删文件时更新索引
- CLAUDE.md 更新文档路径引用
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-01 09:41:14 +08:00
7418 and Claude Opus 4.6
f5ab708a8f
chore: bump v0.21.1
...
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-01 00:49:47 +08:00
7418 and Claude Opus 4.6
65fdeb6dac
fix: bridge 创建的聊天不立即显示在 ChatList
...
Bridge 在服务端通过 createSession() 创建会话,无法触发浏览器端的
session-created 事件,导致 ChatListPanel 不知道有新聊天。
添加 5 秒轮询刷新,查本地 SQLite 开销可忽略,bridge 新建的会话
最多 5 秒即可出现在聊天列表。
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-01 00:49:30 +08:00
7418 and Claude Opus 4.6
6ad821d3af
feat: 多 IM 远程桥接系统 + Bridge 一级导航 + bug 修复
...
**Bridge 系统核心(src/lib/bridge/)**
- bridge-manager: 生命周期编排、adapter 事件循环、会话级并发控制
- channel-adapter: 抽象基类 + 注册式 adapter 工厂
- channel-router: IM 地址 → CodePilot session 自动映射
- conversation-engine: 服务端消费 streamClaude() SSE 流
- permission-broker: 权限请求转发到 IM 内联按钮
- delivery-layer: 出站分片、限流、重试退避、HTML 降级
- telegram-adapter: Telegram 长轮询 + offset 安全水位 + 幂等去重
- security/: 路径校验、危险输入检测、滑动窗口限流
**Telegram 通知 Bot(src/lib/telegram-bot.ts)**
- 独立通知模式,与 bridge 模式互斥
- bridgeModeActive 使用 globalThis 存储,避免 HMR 重置导致轮询冲突
**API 路由**
- /api/bridge: GET 状态查询 + POST start/stop/auto-start
- /api/bridge/channels: 活跃通道列表
- /api/bridge/settings: bridge 设置读写
- /api/settings/telegram: 凭据管理(含 allowed_users 白名单)
- /api/settings/telegram/verify: 连接验证 + chat ID 自动检测
**UI 重构:Bridge 提升为一级导航**
- NavRail 新增 Bridge 图标导航项
- /bridge 页面:BridgeLayout hash 路由,Bridge + Telegram 两个子 tab
- BridgeSection: 总开关、状态、启停、通道开关、适配器状态、默认设置
- TelegramBridgeSection: 凭据配置 + 白名单 + Setup Guide(6 步)
- Settings 移除 Telegram 和 Bridge tab,只保留 4 个核心 tab
**Bug 修复**
- bridge-manager: runAdapterLoop 在 state.running=true 之前被调用,
while 条件同步求值为 false 导致消费者循环不启动。修复为先设 running
再启动 loop
- telegram-bot: bridgeModeActive 改用 globalThis 防止 HMR 丢失状态
- settings/telegram route: TELEGRAM_KEYS 补充 telegram_bridge_allowed_users
**Electron**
- 窗口关闭时 bridge 活跃则最小化到系统托盘而非退出
- 启动时通过 auto-start API 恢复桥接
- preload 暴露 bridge 相关 IPC
**文档**
- docs/bridge-system.md: 完整架构文档
- docs/chat-sdk-integration-feasibility.md: Chat SDK 集成调研
- CLAUDE.md 添加 bridge 文档链接
chore: bump v0.21.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-01 00:18:19 +08:00
7418 and Claude Opus 4.6
f7735e0b9c
fix: 修复关闭最后一个分屏时 setState-during-render 报错
...
- removeFromSplit 中 setSplitSessions updater 内直接调用 router.replace
导致在渲染 AppShell 时触发 Router 组件状态更新
- 改为将导航目标存入 useRef,通过 useEffect 延迟执行 router.replace
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-28 13:30:20 +08:00
7418 and Claude Opus 4.6
7696cbf5c5
refactor: 右侧面板 Tasks/Files 合并为单视图 + 简化 TaskList
...
- RightPanel: 移除 Files/Tasks 双 Tab 切换,改为单视图布局
- 顶部标题改为 TASKS,下方直接渲染 TaskList
- 中间用 mx-4 非贯通分隔线 + border-border/40 降低视觉强度
- 分隔线下方增加 FILES 小标题,再接 FileTree
- TaskList: 大幅简化
- 移除筛选 Tab(全部/进行中/已完成)
- 移除新增任务输入框
- 移除 TaskCard 组件引用,改为 checkbox + 标题单行展示
- 点击切换 completed/pending 状态
- 勾选框使用 foreground 色(黑/白)替代蓝色
- 空状态显示"暂无任务"
- bump version to 0.20.1
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-28 13:27:30 +08:00
7418 and Claude Opus 4.6
b174527719
fix: ChatList 布局优化 + 多语言适配
...
- ChatList 字体从 12px 放大到 13px,图标同步放大,改善点击体验
- ConnectionStatus 胶囊移到顶部 header 区域,与下方按钮左对齐
- "Threads" 改为会话列表上方的小标题,充当分割作用
- ConnectionStatus 文字(Connected/Disconnected/Checking)多语言适配
- "从 Claude CLI 导入" 改为 "从 Claude Code 导入"
- 新增 i18n key: chatList.threads, connection.connected/disconnected/checking
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-28 13:13:30 +08:00
7418 and Claude Opus 4.6
68bb6b60bb
feat: 新增服务商 + 文件上传优化 + AskQuestion 改进
...
新增功能:
- 新增字节火山方舟 (Volcengine Ark) 快速配置预设
- 支持用户输入模型名称,映射到聊天输入框模型选择器
- 模型名称存入 extra_env 的 ANTHROPIC_MODEL
- 新增阿里云百炼 (Aliyun Bailian) 快速配置预设
- 内置 7 个模型供用户直接选择(Qwen 3.5 Plus、Kimi K2.5、GLM-5 等)
- 无需额外配置模型名称
- 两个服务商均使用 @lobehub/icons 品牌图标 (Volcengine, Bailian)
- ProviderManager 图标识别规则新增 volces.com/dashscope 等 URL 匹配
- PresetConnectDialog 新增 model_names 字段类型,渲染模型名称输入框
- models route 动态读取 extra_env 中的 ANTHROPIC_MODEL 展示到模型选择器
修复 & 优化:
- 移除文件上传的类型限制 (ACCEPTED_FILE_TYPES) 和大小限制 (MAX_FILE_SIZE)
现在支持所有文件类型和任意大小,由 API 端处理限制
- AskQuestion 按钮样式对齐权限确认按钮 (h-8 px-3 text-sm font-medium)
- AskQuestion 组件渲染位置从工具调用区域移到流式文本下方
解决长文本输出后用户找不到选择组件的问题
- Anthropic Third-party API 预设的 provider_type 从 "custom" 改为 "anthropic"
修复第三方 Anthropic 兼容 API 无法正确生效的问题
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-28 12:44:07 +08:00
7418 and Claude Opus 4.6
d872f91478
chore: bump v0.19.2
...
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-28 11:45:52 +08:00
7418 and Claude Opus 4.6
ad34fe387b
chore: 禁用 native auto-updater,改为引导用户从 GitHub 下载
...
macOS 上 ad-hoc 签名无法通过 ShipIt 的 kSecCSStrictValidate 校验,
导致热更新始终失败。在获取 Apple 开发者证书之前,暂时禁用 native
auto-updater,改为 browser-mode 检查 GitHub Releases API:
- electron/updater.ts: 注释掉 electron-updater 逻辑,initAutoUpdater
和 setUpdaterWindow 改为 no-op
- electron/preload.ts: 注释掉 updater IPC bridge,前端不再暴露
window.electronAPI.updater
- AppShell.tsx: isNativeUpdater 硬编码为 false,移除 native IPC 订阅
和 native check/download/quitAndInstall 逻辑;保留 browser-mode
的 GitHub API 检查(mount 时 + 每 8 小时),发现新版本时弹窗引导
用户跳转 GitHub Release 页面下载
设置页 UpdateCard 保持不变:「检查更新」按钮通过 /api/app/updates
查询 GitHub,有新版本时显示「查看发布」按钮跳转下载。
TODO: 获取 Apple 开发者证书后,取消注释恢复 native auto-updater。
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-28 11:45:36 +08:00
7418 and Claude Opus 4.6
819f9f401a
chore: bump v0.19.1
...
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-28 01:31:30 +08:00