- 共享
BoundedScrollView(:ui-theme) - 新增方向感知的受限滚动容器:ACTION_DOWN在内容可见且有界时保守抢占手势(不依赖布局完成,消除流式更新中测量时序误判),ACTION_MOVE仅当内容可滚且拖动方向仍有剩余滚动时保持手势(到达边界或内容不可滚时释放,外层列表平滑接管),UP/CANCEL一律释放;shouldHandleDrag/canScrollContent/shouldDisallowOnDown为纯静态决策方法,可脱离 Android 环境单测 - 思考区滚动修复 -
ThinkingBlockView删除私有MaxHeightScrollView,改用共享BoundedScrollView;原实现对canScrollContent()的依赖在内容每帧重测时可能误判 false,导致下拉手势被外层聊天列表抢走;现改为「保守抢占 + 按方向动态交还」,流式输出中在思考区拖动不再整列表乱飞 ToolCallGenericView裸 ScrollView 修复 - 泛型/MCP 工具卡的长内容原本使用无任何拦截逻辑的原生ScrollView,内滚必被外层 ListView 抢占;改用共享BoundedScrollView(220dp),内滚优先、边界交还- 消除无条件 disallow 滚动死区 -
ToolCallShellView/ToolCallAgentView/ToolCallAgentPipelineView各自的私有BoundedScrollView在onTouchEvent/onInterceptTouchEvent中无条件requestDisallowInterceptTouchEvent(true)且从不释放,内容短(不可滚)时外层列表永远无法滚动,表现为"滑动无反应";全部替换为共享类,并删除ToolCallShellView冗余的setOnTouchListener双重拦截 ToolCallReadView长内容有界滚动 - 读取文件的长结果(>300 字符或 >8 行)不再直接撑高聊天列表行,包进 220dpBoundedScrollView内部滚动,内容尾部可达,列表滚动性能提升
ToolCallCardView.updateContent增量钩子 - 接口新增default updateContent(call, result)(默认回退bind,完全向后兼容),为卡片提供「仅内容变化时增量更新」的契约ToolCallBlockView结构/内容签名拆分 - 原signature()包含完整result.content,流式输出每帧内容变化都会removeAllViews+ 重建整棵卡片视图树(几十个 View);现拆分为structureSignature(卡片类型 / 状态 / 参数)与contentSignature(正文):结构变 → 重建,仅内容变 → 调用已存childView.updateContent(...)增量更新,不再销毁重建ToolCallReadView/ToolCallGenericView增量更新 - 缓存消息行 / 输出 section 的 TextView,流式时仅setText;computeTerminalStatus由内容空/非空推导(UNKNOWN↔SUCCESS),状态切换或换行溢出切换滚动容器时回退完整绑定,保证图标/颜色过渡不变ToolCallAgentView增量更新 - 新增纯静态layoutSignature(progressStatus / reviewState / isError / agentId / toolCount / thinking / output 存在性 / name / type / nested 数量)判定结构:签名不变时仅更新 thinking 与输出 Markdown,签名变化(如 running→done)回退完整绑定保留进度条→图标、pills 过渡ToolCallAgentPipelineView保守增量 - summary 计数与状态未变时仅更新汇总 Markdown;有 agent 行的场景保守全量重建(行为不变,性能优先场景为 agents 空时的汇总输出)BaseToolCallView.addMessageRow返回值 - 由void改为返回创建的TextView,供卡片捕获并增量更新文本
- 新增
BoundedScrollViewTest(:ui-theme,13 断言组)覆盖shouldHandleDrag全方向/边界组合、canScrollContent边界、shouldDisallowOnDown八种组合、DOWN→MOVE→反向→UP 完整手势序列决策 - 新增
ToolCallBlockViewSignatureTest(13 例)覆盖结构/内容签名拆分:仅内容变化签名相等、isError/reviewState/id/name/arguments/projectPath 变化签名不等 - 新增
ToolCallAgentViewLayoutSignatureTest(13 例)覆盖 agent 进度 JSON 的 status / tool_call_count / agent_id / output 存在性对布局签名的影响
- 版本号升级到
1.2.6-rc.1 versionCode升级到29
- 新增
:tool-ui模块 - 从:app拆分出独立模块承载全部 ToolCall 卡片视图(ToolCallBlockView、BaseToolCallView)、工厂注册表(ToolCallViewFactoryRegistry)、ToolInfoResolver契约接口;:app改为依赖:tool-ui,解决 app 模块与工具视图的紧耦合 BaseTool.getToolCallViewClass()- 19 个内置工具声明对应视图类(如FileReadTool→ToolCallReadView),移除MainDependencies按分类集中注册 UI 的旧方式;未声明的工具走ToolDisplayCategory分类回退ToolCallViewFactoryRegistry两级解析 - 精确匹配工具声明的视图类 → 分类兜底 →GENERIC兜底;支持按Class和ToolDisplayCategory双维度注册- 工具调用 UI 预览页 - 输出设置新增「工具调用 UI」入口(
ToolCallPreviewScreenView),遍历注册表全部ToolCallViewFactory,用ToolCallPreviewSamples模拟数据渲染每种卡片,便于不跑真实工具时检查 UI - 包结构迁移 -
ToolCall/ToolResult迁至cn.lineai.model.tool;IconButtonView等共享组件与 84 个 drawable 迁至:ui-theme;cn.lineai.tool包整体迁至:feature-tool;ExtensionStore/ExtensionOverviewState迁至:data
- Token 用量追踪 - 新增
TokenUsageTracker(:feature-model),记录最近一次模型响应中服务器观测到的input_tokens/output_tokens;触发检查优先使用观测值(含系统提示 + 工具定义),协议未返回 usage 时回退到ContextManager本地估算 - 软压缩开关 -
AiBehaviorSettings新增softCompactionEnabled字段(默认开启);关闭后只保留 80% 硬触发,压缩行为对齐 codex:仅在上下文占用达到硬阈值时全量压缩并保留最近用户消息 - 硬压缩 codex 对齐 - 硬触发(80%)在模型完成回合 + 工具执行完毕后、继续模型循环前执行(
GenerationFlowController.continueModelAfterTools→shouldAutoCompactMidLoop→startToolLoopContextCompaction);压缩后保留最近用户消息原文(COMPACT_USER_MESSAGE_MAX_TOKENS = 20000),摘要作为用户消息追加,布局:[base] + [retainedRecentUserMessages] + [summary] + [preservedTail] - 压缩重试 -
ContextCompactionService新增MAX_COMPACT_RETRIES重试 + 退避机制;压缩调用使用 codex 风格 handoff-summary 模板(context-compaction-template.txt+context-compaction-summary-prefix.txt),压缩后的 usage 记入TokenUsageTracker作为后续基线 - 会话切换重置 -
TokenUsageTracker在对话切换时由ContextCompactionController.onConversationChanged重置
- 章节化详细指南 -
simple.md(29 章)与pro.md全面重写:覆盖主页/侧边栏导览、权限确认卡语义(同意=已写入生效、拒绝=撤销还原)、模型管理/工具与执行/扩展/主题/安全/数据等每个子设置页的字段级说明;移除本地 GGUF 与实验性键盘避让等未接入功能 - 教程页章节目录 - 新增横向 chips 导航,解析
##章节生成按钮,点击平滑跳转 - 设置页入口 - 设置页顶部新增「查看教程」入口,返回回到设置页
- 命名规范统一 - 多个 setter 重命名为更语义化的前缀:
setPathFromRemoteRoot→applyPathFromRemoteRoot;AgentProgressSession使用mark/update前缀替代set - 不可变对象 -
StorageStatsUiModel改为不可变类,构造函数初始化 + getter;ChatUiState新增防御性拷贝与不可变列表包装 ToolCallUtils移至:tool-ui- 工具调用工具类从:app迁入:tool-ui,消除 app 层对工具视图细节的直接依赖
- 新增
ChatUiStateTest(111 行)覆盖防御性拷贝与不可变列表 - 新增
ToolCallViewFactoryRegistryTest(50 行)覆盖视图类精确匹配与分类回退 - 新增
ToolCallPreviewSamplesTest(37 行)覆盖每种分类的模拟数据生成 - 新增
ContextCompactionServiceTest(91 行)覆盖 token 用量追踪、硬压缩保留最近用户消息、重试机制 - 扩展
ToolBuiltinsTest(18 行)验证所有内置工具声明getToolCallViewClass()
- 版本号升级到
1.2.5-rc.2
- 消息 ID 跨会话冲突根因修复 - 原先
ChatSessionStore.nextMessageId()全局生成m1/m2…,而messages.id为 PRIMARY KEY 且保存走INSERT OR REPLACE,新建会话会覆盖旧会话同 ID 消息行,导致侧边栏只剩最近一次对话;conversation_index无外键清理,检索仍能搜到「幽灵」旧记录。现改为{conversationId}_m{n}按会话隔离 - 落库兼容旧裸 ID -
ConversationRepository.scopedMessageId对历史m1形式写入时加会话前缀({convId}:m1),避免再保存时撞车;ChatSessionStore.sequenceFromMessageId同时解析mN/{id}_mN/{id}:mN - 删除/清空同步清索引 -
deleteConversation/clearAll/StorageStatsRepository.clearChatHistory同步删除conversation_index(及 FTS),避免删会话后检索残留 - 进后台主动落盘 -
MainCoordinator.onEnterBackground调用persistCurrentConversation(),降低onPause后被系统杀进程丢未落库内容的概率
file_edit默认唯一匹配 - 多处匹配且未设replace_all=true时失败不写盘,并提示提供更唯一的old_string或开启全量替换;默认只替换唯一匹配的第一处- 用户撤销写操作后模型不再读成功文案 -
ToolMessageController.updateToolReview在rejected时将 tool 消息标isError=true并改写 content 为明确「用户已拒绝并还原」说明;嵌套 agent 结果同步更新is_error/content - OpenAI 工具错误前缀 -
OpenAiMessageSerializer对isToolError结果加Tool <name> failed:\n前缀(与 Codex 路径一致),避免协议无结构化 error 字段时模型误判成功 ToolArgsCleaner保留多行空白 - 字符串内未转义的\n/\r/\t转为 JSON 转义,避免增量old_string被拍扁导致匹配失败
- 从 GitHub 安装 Skill - 新增
GitHubSkillInstaller:支持github.com/org/repo、blob/tree 路径、raw.githubusercontent.com的SKILL.md;仓库用 codeload zip 下载并查找SKILL.md。扩展 → Skills → 添加菜单新增「从 GitHub 安装」 - Skills 多选批量删除 - 扩展详情页长按 Skill 进入多选,顶部显示已选数量,可批量删除;
ExtensionStore.deleteSkills/ExtensionManagementController.deleteExtensions贯通 - 工作区 FileProvider - 新增
WorkspaceFileProvider(content://{appId}.workspace/...)暴露内部files/.linecode;Skills 页增加「分享工作区目录」入口(WorkspaceShareHelper)
- 思考深度 Auto -
AiBehaviorSettings.REASONING_AUTO;LLM 设置与/model级别列表增加 Auto;协议层auto视为开启思考,具体 effort 映射为medium(MiniMax 仍走 adaptive) - 新增模型提供商预设 - Groq、Together AI、SiliconFlow、MiniMax、Ollama、LM Studio(OpenAI 兼容),
ModelProviderPresets+ 三语文案同步
- 新增
ConversationMessageIdScopeTest、GitHubSkillInstallerTest、AiBehaviorSettingsAutoTest - 扩展
ChatSessionStoreTest、ToolMessageControllerTest、ToolBuiltinsTest(file_edit 唯一/全量)、ToolArgsCleanerTest、OpenAiCompatibleProtocolTest、SlashCommandCatalogTest
- 版本号升级到
1.2.4 versionCode升级到27
- 全量 i18n 替换与术语统一 - 将项目内全部硬编码中文提示、日志、枚举标签、错误文案统一替换为英文,覆盖
feature-model、core-model、feature-tool、data、core-security、app等模块:包含ChatMode.promptContext中 Chat / Plan / Control / Agent 四种会话模式说明、SystemPromptProvider调用的全部feature-model/src/main/assets/prompts/*.txt模板(system-prompt-template.txt、agent-role-coding-local.txt/agent-role-coding-remote.txt/agent-role-explore-local.txt/agent-role-explore-remote.txt、memory-extraction-template.txt、learning-context-template.txt、work-directory-template.txt、tone-chat-template.txt、tone-coding-template.txt、todo-usage-template.txt、todo-state-template.txt、model-identity-template.txt、image-understanding-tool-system.txt、skill-extraction-template.txt)、ModelProtocolType协议标签(OpenAI / Codex / Anthropic / Local)、SheetOption.getDeleteActionLabel、协议层错误描述、分享格式前缀、工具异常提示、工具提示词渲染等 :app新增 50+ 条多语言字符串 - 在app/src/main/res/values/strings.xml与values-zh/strings.xml同步补充model_provider_preset_*_label/desc/hint系列(custom / deepseek / glm / mimo / mimo-token-plan / kimi / qwen / openai / claude / gemini / openrouter / codex 共 12 套)、memory_extraction_json_only、agent_execution_completed、agent_pipeline_completed、user_rejected_tool、remote_file_tree_loading、skill_source_not_found、skill_ssh_directory_hint、skill_zip_entry_out_of_bounds、extension_draft_missing_fields、extension_draft_invalid_json等:app新增俄文资源 -app/src/main/res/values-ru/strings.xml一次性补齐 1251 行,覆盖模型预设、内存抽取、Agent 执行、技能草稿等所有英文新增文案:feature-tool新建模块级资源 - 全新feature-tool/src/main/res/values/strings.xml、values-zh/strings.xml、values-ru/strings.xml(228 / 228 / 55 行):按工具分组为FileReadTool/FileEditTool/FileWriteTool/FileDeleteTool/GlobTool/ListDirectoryTool/AgentTool/AgentPipelineTool/TodoUpdateTool/ImageGenerationTool/ImageUnderstandingTool/WebSearchTool/WebFetchTool/WebSearchService/CustomMcpHttpTool/CustomAgentExtensionTool/ImageResponseParser/ShellExecuteTool/FileToolPathPolicy/ToolArgs/ExceptionUtils共 21 组错误与状态文案,以及 7 个工具动作标签(tool_call_action_read/search/fetch/match/list_dir/image_generation/image_understanding)- Phone 工具俄文补齐 -
feature-tool/src/main/res/values-ru/strings.xml补充 55 行:phone 工具动作名(tool_call_phone_action_screenshot/click/swipe/long_press/view_hierarchy/click_view/global_action/default)、phone 工具摘要、全局动作本地化名(back / home / exit_app / recents / notifications / quick_settings / power_dialog / lock_screen / unknown)、phone_tool_accessibility_*提示与phone_tool_screenshot/click/swipe/long_press/view_hierarchy/click_view/global_action_*等描述/成功/失败文案 - 模型预设抽取为资源键 -
ModelProviderPreset移除label/desc/hint内置字符串字段,改用新增的cn.lineai.ui.util.ModelProviderPresetStrings注册表(register(id, labelResId, descResId, hintResId)+getLabel/Desc/Hint(Context, id)),由:app在 strings.xml 提供多语言文案,ModelProviderPresets同步移除文本构造参数 ToolContext字符串解析 -ToolContext新增StringResolver字段与getString优先走stringResolver,避免在无 Android Context 场景下文案无法解析;内置工具全部getDescription/getActionName/promptSupplement/ 错误返回改用英文;FileReadTool/ImageGenerationTool/ImageUnderstandingTool错误返回全部经context.getString(R.string.tool_*)解析- Bing RSS 搜索 market 动态化 -
BingRssSearchProvider的mkt参数从硬编码zh-CN改为Locale.getDefault().toLanguageTag(),缺失回退en-US,跟随系统语言 FakeResourceContext测试桩 - 新增feature-tool/src/test/java/cn/lineai/tool/FakeResourceContext解析feature-tool/src/main/res/values/strings.xml并通过R.string.*反射查表,单元测试中可替代Context.getString(被 Robolectric/Android 框架默认 stub 抛 "not mocked"),ToolBuiltinsTest全面接入
ModelProtocolType携带协议能力 - 枚举增加dedicatedCompression字段与supportsDedicatedCompression()方法;OPENAI_COMPATIBLE/CODEX_RESPONSES标记为true,ANTHROPIC_MESSAGES/LOCAL_GGUF标记为false,ModelConfig删除@Deprecated public static boolean supportsDedicatedCompression(ModelProtocolType),统一通过枚举属性判断ModelConfig构造器收敛 - 移除 3 个@Deprecated旧构造器(含compressionModelEnabled/compressionModelAuto/compressionModelId/contextSize全字段版),保留Builder模式;compressionModelEnabled在构造时直接按protocolType.supportsDedicatedCompression()二次校正- 模型目录拉取接口化 - 新增
cn.lineai.ai.protocol.CatalogFetcher接口与OpenAiCatalogFetcher/AnthropicCatalogFetcher/CodexCatalogFetcher三个实现;ModelCatalogClient重构为注册表 + 通用fetch(...)调度,删除 78 行硬编码分支 - Codex 协议拆分 - 从
CodexResponsesProtocol抽离CodexRequestBuilder(149 行,请求体拼装)和CodexOutputMerger(191 行,SSE 输出合并 +function_call/custom_tool_call/reasoning/output_text归并),CodexResponsesProtocol大幅缩减;OpenAiCompatibleProtocol同步拆出OpenAiMessageSerializer(74 行,消息序列化) ModelAddOptionsScreenView/ModelAddScreenView拆分 - 模型添加页 716 → 缩减,新增ModelCompressionSectionView(333 行,压缩模型配置区:query 按钮、loading 态、picker 选择、custom id 切换)、ModelFormHelper(88 行,label / input / toggle / switch tint / value / detachFromParent 复用工具)、ModelPickerDialog(106 行,底部弹窗,列出目录模型 + 自定义 id 选项)
- 统一 thinking 参数格式 - 各
ReasoningRequestStrategy统一按context.isEnabled()与context.getEffort()写入请求体;DeepseekReasoningStrategy移除对AiBehaviorSettings.REASONING_MAX的硬编码判断,直接body.put("reasoning_effort", context.getEffort());DefaultReasoningStrategy在AiBehaviorSettings.REASONING_MAX.equals(effort)时映射为"xhigh",否则原样写effort;MinimaxReasoningStrategy额外写入body.put("thinking", new JSONObject().put("type", enabled ? "adaptive" : "disabled")) - ComposerView 模型搜索 -
/model命令候选列表新增大小写不敏感子串匹配:name/modelId/id/providerLabel任意字段包含查询词即保留;模型下拉候选项从只显示 id 改为modelDisplayName(name 优先,回退 apiId,再回退 providerLabel)+modelDisplayDetail(providerLabel · apiId),无 apiId 时只显示 providerLabel
ToolResult工厂化 - 统一ToolResult.success(output)/error(error)/withReview(...)/of(...)静态方法替代new ToolResult(...);ToolExecutor内部错误返回改用ToolResult.error/ToolResult.of- 工具默认权限配置 - 新增
cn.lineai.data.repository.ToolSettingsStore默认实现细节(toolSettingsRepository = new ToolSettingsRepository(resourceProvider, settingsRepository, webSearchConfigRepository, phoneControlRepository, categoryResolver)),ToolPermissionService新增(86 行)将权限判断从ToolExecutor中拆出 - DiffRecorder 抽离 - 新增
cn.lineai.tool.DiffRecorder(57 行),把shouldRecordDiff(tool)与executeWithDiff(tool, input, context)从ToolExecutor抽出;ToolExecutor持有DiffRecorder引用,需要时委托;ToolExecutor构造签名同步调整为 7 参数版 + 8 参数(多learningContextStore注入),MainDependencies接入新签名 PhoneControlToolSupport拆分与接口化 - 原app/.../tool/builtin/PhoneControlToolSupport工具类(37 行壳)拆为:feature-tool模块的PhoneControlToolSupport(85 行,绑定无障碍服务LineCodeAccessibilityService.getReadyInstance(ctx)),新增cn.lineai.tool.PhoneControlService接口(28 行)解耦手机工具与无障碍服务实现;AccessibilityStateProvider接口(9 行)由LineCodeAccessibilityService.isServiceEnabled实现- 内置工具操作名/图标 - 25+ 个内置工具统一新增
getActionName(Context)返回R.string.tool_call_action_*多语言资源与getActionIcon()返回ICON_*常量;FileReadTool错误提示从硬编码中文改为context.getString(R.string.tool_file_read_*)共 10 个资源 ToolRegistry扩展 - 接受ExtensionStore注入并对外暴露setExtensionStore;BuiltInToolProviders注册新内置工具时同步带NAME常量ToolContext字段扩展 - 构造器新增LearningContextStore与StringResolver字段及对应 Builder 方法;BaseTool.isConcurrencySafe/BaseTool.execute路径与ToolSettingsRepository/LearningContextStore全部接入新字段
agent_output工具 - 新增cn.lineai.tool.builtin.AgentOutputTool(185 行,NAME = ToolNames.AGENT_OUTPUT),通过ToolContext.getAgentResultStore()按agent_id拉取会话内已存的 Agent 结果;参数include: output返回完整正文(受ToolResult.MAX_TOOL_RESULT_CHARS截断),include: meta返回agent_id / status / type / description / preview / error / async / tool_call_count字段;Agent 仍 running 时返回结构化running状态 JSON;isAllowedInReadonlyMode = true,isConcurrencySafe = true,getDisplayCategory = READ,getActionIcon = ICON_BOT- 异步 Agent 执行 -
AgentTool参数新增async: boolean(仅 explore Agent 允许;sub-coding 传async=true时立即返回错误);AgentExecutionController.runAgentTool检测async时agentResultRegistry.allocateId()+runningRecord落库 → 写入ToolResult.reviewState = "running"+host.runInBackground(...)异步跑runAgentLoop,完成后用finishAgentWithCompact落定结果并把compactJSON 替换原 tool result - Agent 结果注册表 - 新增
cn.lineai.mvp.agent.AgentResultRegistry(170 行,会话级LinkedHashMap<String, AgentResultRecord>+AtomicInteger id分配器,提供allocateId / put / getRecord / get / setFullOutput / toCompactJson),AgentResultRecord(220 行,含agentId / toolCallId / status / type / description / preview / fullOutput / thinking / progressJson / toolCallCount / error / async / generationId / updatedAtMs+running(...)工厂 +withPreview/withStatus/withFullOutput不可变更新);ToolContext.AgentResultStore抽象由agentResultRegistry实现并由GenerationFlowController通过ToolContext.Builder.agentResultStore(...)注入 - Agent 工具返回压缩 -
finishAgentWithCompact把原本"任务标题 + 类型 + 工具调用次数 + 输出"的长字符串结果替换为linecode_agent_ref精简 JSON(agent_id / status / type / description / preview / async / tool_call_count),完整正文留在agentResultRegistry,由后续agent_output拉取 - PipelineProgressSession 线程安全 -
PipelineProgressSession所有 setter /publish/payload增加synchronized (lock)块;新增Object lock字段;setStatus/setFinalSummary/beginAgent/updateAgent/finishAgent/terminate/publish/payload等方法全部加锁,buildPayload拆为buildPayloadLocked,countStatus/countFailed拆为*Locked - 工具预算原子化 -
runAgentTool/runAgentPipelineTool/runAgentLoop中int[] toolCallBudget替换为AtomicInteger toolCallBudget,跨 sub-agent 调用时toolCallBudget.incrementAndGet()共享主流程toolCallLimit - AgentTool 显示与图标 -
AgentTool新增getActionIcon = ICON_BOT、getActionName = "Agent";BaseTool新增ICON_BOT常量;ToolCallAgentView卡片元信息新增agent_id标签,title 文本由AgentToolResultDisplay.description提供避免显示空内容
MemoryUpdateTool持久化用户偏好 - 新增cn.lineai.tool.builtin.MemoryUpdateTool(133 行,NAME = "memory_update"),参数content(≤MAX_CONTENT_CHARS = 320,超出截断 +。)+scope: user / project / environment;通过ToolContext.getLearningContextStore().saveMemory("", scope, homePath, content)写入;拒绝包含api key/password/secret/cookie/token/私钥/密码/密钥/sk-等敏感关键词的内容(tool_memory_sensitive_rejected);返回tool_memory_updated;isConcurrencySafe = true,getDisplayCategory = READ,getActionIcon = ICON_BOOK_OPEN- 记忆批量删除 -
LearningContextStore接口新增deleteMemories(List<String> ids);MemorySettingsScreenView从ScreenScaffoldView重构为LinearLayout,Listener新增onMemoriesDeleted(List<String> ids);长按 / 点击多选按钮进入multiSelectedIds状态,顶部切换为ScreenHeaderView("Selected: N")+ 关闭 +TRASH_2按钮;确认弹窗screen_memory_delete_selected_message批量删除;setBackgroundColor(LineTheme.ACCENT_MUTED)高亮已选 - 记忆提取优化 -
MemoryExtractionService重构:构造函数改为MemoryExtractionService(ResourceProvider, LearningContextStore, ExtensionStore, PromptTemplateRepository),移除Context硬依赖;MAX_MEMORIES由 5 改为 3;新增MIN_KEEP_CONFIDENCE = 0.78/RULE_CONFIDENCE = 0.88/MODEL_DEFAULT_CONFIDENCE = 0.82常量;新增hasDurableSignal(userInput, transcript)触发条件,关键词包括"记住/长期/始终/永远/禁止/必须/偏好/习惯/全局/这个项目/本项目"等 30+ 个中英文长效信号;未命中时跳过模型调用与规则抽取,直接走技能提取;scope解析新增normalizeScopeOrEmpty区分"未知"与"user",未知 scope 不再默认 user;modelContent提取改用R.string.memory_extraction_json_only - 记忆提取调度迁移 -
GenerationFlowController.scheduleMemoryExtractionIfNeeded整段删除(含memoryExtractionService字段、构造器注入与linecode-memory-extract后台任务),记忆提取由MainCoordinator单独调度,控制器字段收敛
- 修复后台切到前台时强制中断生成 - 新增
cn.lineai.mvp.ActivityGenerationLifecyclePolicy策略类:shouldStopGenerationOnStop(isFinishing)仅当Activity.isFinishing()为 true 时返回 true;shouldStopGenerationOnStart()恒为 false;MainActivity.onStop/onStart改为通过策略判断后调用presenter.resetGenerationState(),避免 Home / 多任务切回杀掉正在进行的 LLM 流、auto-reject 待审工具、关闭 keep-alive;onDestroy仍无条件presenter.destroy();MainCoordinator.resetGenerationStateJavadoc 明确只在用户主动停止 / Activity finishing / destroy 三个场景调用 AgentToolResultDisplay工具类 - 新增cn.lineai.ui.component.toolcall.AgentToolResultDisplay(113 行),统一解析linecode_agent_progress/linecode_agent_pipeline_progress/linecode_agent_ref三种结构化 JSON;提供progressPayload / displayOutput / progressStatus / nestedToolCalls / toolCallCount / description / type / thinking8 个静态方法;displayOutput在 JSON 包裹时优先返回output字段再回退model_content,避免 Markdown 块直接渲染原始 JSON;非 JSON 文本中检测到"输出:\n"前缀则取其后正文ToolCallAgentView改用AgentToolResultDisplay- 删除 60+ 行手写progressPayload私有解析逻辑,全部改用AgentToolResultDisplay工具方法;running状态判定新增outerReviewState == "running";toolCount优先从 progress JSON 拿,其次解析工具调用:文本标签ToolCallGenericView同样接入 - 当结果内容是linecode_agent_*_progress结构时改走AgentToolResultDisplay.displayOutput取人类可读正文,避免 generic view 把 raw JSON 整段塞进 Markdown;空内容时回退tool_call_agent_failed/tool_call_agent_done提示ToolDisplayResolver内置 agent 分类 -fallbackDisplayCategory命中"agent"返回ToolDisplayCategory.AGENT;命中"agent_pipeline"返回ToolDisplayCategory.AGENT_PIPELINE;agentx_前缀继续返回AGENT;mcpx_仍为GENERIC
- 新增 8 个解耦接口 -
cn.lineai.ai.PromptTemplateProvider(11 行)、cn.lineai.ai.SkillPromptProvider(9 行)、cn.lineai.resource.ResourceProvider(13 行,openAsset/getString)、cn.lineai.resource.SystemConfigProvider(13 行,isDarkModeEnabled/getSdkInt/getFilesDirPath)、cn.lineai.service.AccessibilityStateProvider(9 行,isAccessibilityEnabled)、cn.lineai.tool.ToolCategoryResolver(9 行)、cn.lineai.tool.ToolPromptRenderer(9 行)、cn.lineai.tool.PhoneControlService(28 行);仓库层不再依赖具体实现,可由测试桩或 DI 容器替换 - 仓库层解构 Android Context -
KeepAliveRepository/UserAgreementRepository/SshConfigRepository/AiBehaviorSettingsRepository/ChatModeRepository/InputSettingsRepository/OutputSettingsRepository/ThemeSettingsRepository/ExtensionRepository/IpcProviderRepository/ProjectRepository/PromptTemplateRepository/WebSearchConfigRepository/SettingsRepository/ConversationRepository/DiffRepository/ModelRepository全部改为构造注入LineCodeDatabase/ResourceProvider/SystemConfigProvider/WorkspacePaths;MainDependencies一次性LineCodeDatabase.getInstance(appContext)+ 构造ContextResourceProvider/ContextSystemConfigProvider共享 LearningContextStore拆分 - 接口新增deleteMemories(List<String> ids);业务编排buildLearningContext/getOverview抽到cn.lineai.service.LearningContextService(51 行);MemoryPromptBuilder由cn.lineai.ai.prompt包移至cn.lineai.ai.prompt并接受WorkspacePaths/PromptTemplateRepository注入DiffStore接口扩展 - 新增markReverted(String diffId)方法;DiffRepository实现迁移到cn.lineai.data.service.FileRestorer(36 行,文件恢复),DiffRepository.revertDiff不再直接写文件UrlPolicy实例化扩展 - 从final class+ 全部static方法改为可继承实例类(public class UrlPolicy),持有DEFAULT单例;cleartextHosts/privateNetworkPredicates通过addCleartextHost(String)/addPrivateNetworkPredicate(Predicate<String>)注册;registerDefaultCleartextHosts默认注册 localhost / 127.0.0.1 / 10.0.2.2 / ::1;registerDefaultPrivateNetworkPredicates默认注册 192.168.* / 10.* / 172.16-31.*;checkNormalizeHttpOrHttpsUrl/checkNormalizeHttpOrLocalCleartextUrl/checkRequireHttpOrLocalCleartextUrl/checkIsAllowedCleartextHttpUrl由静态方法改为实例方法(保留兼容调用)
- 重试机制 -
GenerationFlowController引入MAX_RETRIES = 3/RETRY_DELAY_MS = 5000L;新增私有retryableModelStream(generationId, model, cancellationToken, messages, usedToolCallCount, attempt, userInput)方法;ModelCompletionException触发时进入handleModelError:取消或已用满 3 次则failGeneration(generationId, id, host.formatModelFailed(error));否则从messages列表移除失败的 assistant 消息,插入ChatMessage.retryNotice(id, host.formatRetryNotice(attempt+1, MAX_RETRIES, error))通知气泡,主线程postDelayed(RETRY_DELAY_MS)后再次调用retryableModelStream(..., attempt+1, ...);后台任务名按attempt == 0区分linecode-model-stream/linecode-model-stream-retry - Host 回调扩展 -
GenerationFlowController.Host新增String formatRetryNotice(int attempt, int maxRetries, String error)/String formatModelFailed(String error);GenerationFlowHost实现走coordinator.context().getString(R.string.model_retry_attempt / model_retry_failed, ..., StringUtils.decodeUnicodeEscapes(error)),错误文本先经 Unicode 转义解码 - ChatMessage 新增重试通知类型 -
ChatMessage.retryNotice(id, content)工厂方法;modelSwitchNotice文案从中文 "模型已从 ... 更改为 ..." 改为 "Model changed from ... to ...";ChatMessageListView通知视图创建方法createModelSwitchNotice改名为通用createNoticeView,ViewType 常量VIEW_TYPE_MODEL_SWITCH改名为VIEW_TYPE_NOTICE,同时支持模型切换与重试通知 - 三语资源 -
app/src/main/res/values/strings.xml/values-zh/strings.xml/values-ru/strings.xml同步新增model_retry_attempt/model_retry_failed两条
- 导入导出数据库依赖注入 -
LineCodeArchiveService/LineCodeImportService构造注入LineCodeDatabase而非依赖Context;ArchiveSecretRedactor(124 行)增补可注册敏感字段与命名关键字 - StorageStatsRepository - 36 行调整,统计口径从
MessageTextChunkStore.totalLength聚合 MemoryRanker适配 - BM25 排序器 22 行调整,配合LearningContextService业务编排分离SkillRepository业务编排扩展 - 123 行扩展,把 Skill 文件 IO 委托给SkillFileManager,自身只保留数据库 CRUDChatModeRepository.applyMode- 权限申请与模式应用解耦,新增applyPermissionForMode单独处理权限;SettingsManagementController透传回调
- 新增
ActivityGenerationLifecyclePolicyTest(22 行)覆盖 home / 任务切换 / 退出 / 回前台 4 种生命周期的生成终止策略 - 新增
ToolDisplayResolverFallbackTest(26 行)覆盖agent/agent_pipeline/agentx_*的 fallback 分类 - 新增
AgentToolResultDisplayTest(57 行)覆盖结构化 JSON 解析、output字段优先级、未知 JSON 安全降级 - 扩展
AgentOutputToolTest(115 行)覆盖 agent_id 缺失、store 不可用、未知 id、运行中、含错误、空正文、超大输出截断、include=meta 等场景 - 扩展
AgentResultRegistryTest(149 行)覆盖 id 分配、状态变更、压缩 JSON 输出 - 扩展
PipelineProgressSessionTest(92 行)覆盖多线程并发下状态变更与最终 payload 构建 - 新增
PipelineDependencyResolverTest(72 行)覆盖 Pipeline 依赖图与并行层划分 - 扩展
ToolBuiltinsTest(65 行)覆盖英文文案下的全部内置工具描述、参数、动作名;接入FakeResourceContext解决单元测试无 Context 问题 - 扩展
GenerationFlowControllerTest(+11 行)覆盖MemoryExtractionService字段移除后的构造器签名变化 - 扩展
ToolSettingsRepositoryTest(+56 行)覆盖ToolCategoryResolver/WebSearchConfigRepository/PhoneControlRepository注入后的权限与分类解析
- 版本号升级到
1.2.3 versionCode升级到26
- 10 个新 Gradle 模块 - 从单模块
:app拆分为多模块架构,新增:core-model(纯数据类 / DTO / 枚举)、:core-api(接口抽象)、:core-security(UrlPolicy、SimpleHttpClient)、:ui-theme(LineTheme及共享 UI 基础设施)、:markdown(Markdown 渲染,commonmark + GFM tables)、:data(SQLite schema、仓库、导入导出归档、错误日志)、:feature-tool(BaseTool、ToolRegistry、全部内置工具)、:feature-model(ModelProtocol、ModelProtocolFactory、四种协议实现、ContextManager、ContextCompactionService、提示词模板)、:feature-ssh(SshService、SshConnectionPool、SshCommandExecutor、TermuxHelper)、:feature-share(导出 / 分享 / PDF)。settings.gradle.kts新增includeBuild("build-logic")composite build 共享约定插件。 - 代码迁移 -
:app模块中cn.lineai.model.*→:core-model;cn.lineai.tool.ToolInfo/ToolNames/ToolCategory/ToolDisplayCategory/ModelServiceProvider→:core-api;cn.lineai.security.*→:core-security;cn.lineai.ui.theme.*→:ui-theme;cn.lineai.ui.markdown.*→:markdown;cn.lineai.data.*+cn.lineai.log.*+cn.lineai.workspace.*→:data;cn.lineai.tool.*→:feature-tool;cn.lineai.ai.*+cn.lineai.context.*→:feature-model;cn.lineai.ssh.*→:feature-ssh;cn.lineai.share.*→:feature-share。app/src/main/assets/prompts/*.txt提示词模板 →:feature-model。 - 新增基类与工具 -
BaseRepository(公共 Cursor 辅助方法)、FileTreeBaseRepository(文件树仓库公共基类)、ExceptionUtils(工具异常格式化)、AbstractToolCallBuilder(协议 tool_call 构建公共逻辑)、DefaultModelServiceProvider(默认ModelServiceProvider实现)、ReasoningDeltaExtractor(推理增量提取)。 - 循环依赖打破 -
:feature-tool不得引用cn.lineai.ai;:feature-model只引用:core-api中的ToolInfo/ToolNames/ToolCategory;ai ↔ tool循环依赖已消除。
- 50% 软触发 -
ContextCompactionService引入SOFT_COMPACT_TRIGGER_RATIO = 0.5,上下文窗口占用超过 50% 时触发软压缩:最早 70% 可压缩消息被总结,最近 30%(SOFT_COMPACT_TAIL_KEEP_RATIO)原文保留。布局:[head(excludeFromContext)] + [summary] + [tail(original)] + [preservedTail] + [progressDone]。 - 80% 硬触发 -
shouldCompact在 80% 占用时执行全量压缩兜底。ChatInteractionController在每次请求前检查软触发(未硬触发时)。 - 分段存储防 OOM -
ContextCompactionService用List<String>逐段拼接转录文本,每段 ≤TRANSCRIPT_SEGMENT_MAX_CHARS = 256KB,避免单个StringBuilderOOM。移除固定大小截断(MAX_MESSAGE_CONTENT_CHARS/MAX_TRANSCRIPT_CHARS)。 - 大堆内存 -
AndroidManifest.xml设置android:largeHeap="true"支持大转录。 - 压缩控制器 -
ContextCompactionController新增startSoftContextCompaction/finishSoftContextCompaction驱动流程;OutOfMemoryError在服务和控制器中均被捕获作为最后兜底。
ContextSizeParser- 新增cn.lineai.model.ContextSizeParser(:core-model),解析用户输入如128K、1m、128000为整数 token 数。ModelContextParser- 新增cn.lineai.model.ModelContextParser(:core-model),兼容旧{id}[{size}]后缀格式,提供parse(ModelConfig)/apiModelId(ModelConfig)方法。协议统一调用apiModelId(ModelConfig)发送请求,剥离[size]后缀。ModelConfig.contextSize-contextSize作为一等字段由ContextSizeParser解析;UI 使用纯文本字段输入;model_configsSQLite 表新增context_size列。
ToolResult.truncateContent()- 新增静态方法,50KB 上限截断:输出 ≤ 50KB 原样返回,> 50KB 保留前 25KB + 截断提示 + 后 25KB(中间截断,保留首尾)。FileReadToolKB 参数 - 文件读取参数从行制(start_line/end_line/offset/limit)改为 KB 制(start_kb/end_kb),50KB 上限;超过 1MB 的文件拒绝读取并返回提示。ShellExecuteTool输出截断 - Shell 输出超过 50KB 时自动截断(首 25KB + 截断消息 + 尾 25KB)。- 压缩期截断 -
ContextCompactionService构建转录时对消息内容、工具调用参数、推理内容执行截断,防止超大内容进入上下文。 - 安全校验 -
ToolMessageController在写入工具结果前检查内容大小。
- 图片选择按钮 -
ComposerView在附件+按钮右侧新增图片按钮(IconButtonView.IMAGE),点击打开系统图片选择器(ACTION_OPEN_DOCUMENT,image/*)。选中图片经压缩(长边 ≤ 1568px,JPEG q=85,>3.5MB 再降级)后 base64 编码,通过ChatInteractionController.sendMessageWithImage→ImageInputPayload.rawInputJson注入消息。协议自动检测ImageInputPayload.KIND并按供应商格式输出(OpenAIimage_url、Anthropicimage.source.base64、Codexinput_image)。 - 绕过路径保护 - 安全设置页新增"绕过路径保护"开关(
OutputSettings.bypassPathProtection,默认关闭)。开启后FileToolPathPolicy.resolve跳过工作区边界校验直接返回规范路径;ToolContext.bypassPathProtection由ToolExecutor.injectDependencies传播;AgentExecutionController.validateAgentWriteScope在绕过开启时跳过write_scope检查。开启时显示警告对话框需用户确认。所有文件类工具(FileReadTool/FileWriteTool/FileEditTool/FileDeleteTool/GlobTool/ListDirectoryTool/ImageUnderstandingTool)自动遵守此标志。
BingRssSearchProvider- 新增cn.lineai.tool.builtin.search.BingRssSearchProvider,利用 Bing RSS 搜索接口提供免费网页搜索能力(无需 API key)。解析 RSS/Atom XML 提取标题、摘要、URL。- 搜索配置优化 -
WebSearchConfig新增bingRss提供商标识字段;ToolSettingsScreenView搜索配置区域支持 Bing RSS 选项;WebSearchService适配新 provider;ToolSettingsRepository搜索配置逻辑重构。 - 测试 - 新增
BingRssSearchProviderTest(49 行)覆盖 RSS 解析。
ToolArgsCleaner- 新增cn.lineai.tool.ToolArgsCleaner(移至:feature-tool),对模型返回的工具参数字符串做清洗:剥离 Markdown 代码围栏、NFKC 归一化并移除零宽字符、删除注释与控制字符、移除对象/数组尾部多余逗号、将简单单引号字符串转为双引号。合法 JSON 原样返回,空/空白返回{}。ToolExecutor接入 -ToolExecutor.execute在new JSONObject(...)之前先调用ToolArgsCleaner.clean(toolCall.getArguments()),降低模型输出带围栏、注释、单引号或多余逗号时参数解析失败的概率。- 测试 - 新增
ToolArgsCleanerTest覆盖空输入、Markdown 围栏、注释、尾部逗号、单引号、控制字符等场景。
- Agent 类型展示 -
ToolCallAgentPipelineView/ToolCallAgentView优化 Agent 角色类型标签展示,区分编程型/探索型 Agent。 - 参数补全 -
ToolCallBlockView工具调用卡片参数补全逻辑优化。 - 状态显示修复 - 修复
ToolCallReadView/ToolCallWriteView在某些状态下进度圈不消失的问题;BaseToolCallView新增TerminalStatus枚举和computeTerminalStatus统一终态判断。
ModelProtocol默认方法 -ModelProtocol接口新增supportsNativeTools()/supportsContextCompaction()/supportsImageGeneration()/supportsImageUnderstanding()4 个default方法返回true;各协议按需覆写。AbstractToolCallBuilder- 新增cn.lineai.ai.protocol.AbstractToolCallBuilder,提取OpenAiCompatibleProtocol/AnthropicMessagesProtocol/CodexResponsesProtocol共用的 tool_call JSON 构建逻辑。ReasoningDeltaExtractor- 新增cn.lineai.ai.protocol.reasoning.ReasoningDeltaExtractor,统一提取各协议流式推理增量内容。ToolCallTextParser增强 - 工具调用文本解析健壮性提升,解析失败返回空数组而非抛异常。ModelCatalogClient重构 - 模型目录客户端清理冗余逻辑。
- 新增 30+ 条字符串 - 图片选择、路径保护、上下文大小、搜索配置、安全设置等相关文案同步添加到
values/strings.xml与values-zh/strings.xml,各子模块(data、markdown、feature-ssh)各自持有资源文件。 - 模块级资源隔离 -
:data、:markdown、:feature-ssh等模块拥有独立的strings.xml,不再全部集中到:app。
- 版本号升级到
1.2.2 versionCode升级到25
- 跳过已生成的隐藏摘要 -
ContextCompactionService.selectCompactableMessages与ContextCompactionController三处过滤逻辑统一:消息为hidden且responseInputItemJson非空时视为已压缩摘要,不再参与下一次压缩;compactStatus非空的压缩进度块同样跳过。修复历史摘要在多次压缩循环中被反复覆盖、导致早期上下文丢失的问题。 - 摘要必须进入上下文 -
ContextCompactionController.createCompactedMessages构造摘要消息时显式将excludeFromContext置为false(避免链式withResponseInputItemJson基于旧副本意外保留true),保证压缩后的摘要能被后续模型请求看到,防止模型侧出现"上下文被清空"的幻觉。 - 统一可压缩内容判断 -
hasCompactableContent与isCompactionNeeded路径均接入同一规则,避免不同入口对隐藏摘要/压缩块的处理不一致。
ToolArgsCleaner参数清洗 - 新增cn.lineai.tool.ToolArgsCleaner纯工具类,对模型返回的工具参数字符串做清洗:剥离 Markdown 代码围栏、NFKC 归一化并移除零宽字符、删除注释与控制字符、移除对象/数组尾部多余逗号、将简单单引号字符串转为双引号。合法 JSON 原样返回,空/空白返回{}。ToolExecutor接入清洗 -ToolExecutor.execute在new JSONObject(...)之前先调用ToolArgsCleaner.clean(toolCall.getArguments()),降低模型输出带围栏、注释、单引号或多余逗号时参数解析失败的概率。
GenerationFlowController不回退保护 -publishToolResultProgress新增resolveProgressReviewState从进度 JSON 的status字段解析状态;若该工具已有完成/失败等终态结果,异步进度不再把它拉回running,修复进度圈在某些异步进度发布后永不消失的问题。ToolMessageController.currentReviewState- 新增按toolCallId查询当前reviewState的方法,供进度发布时判断是否为终态。- Agent Pipeline 进度发布 -
AgentExecutionController.runAgentPipelineTool构造PipelineProgressSession时注入ProgressPublisher,子 Agent 进度变化时直接调用host.addOrReplaceToolResult+host.render,让流水线卡片状态与底层结果同步。 - 流水线完成判定修复 -
ToolCallAgentPipelineView.bind完成判定优先以进度 JSON 的status == "done"为准(不再单纯依赖reviewState时序),异常时仍按error处理,解决流水线已完成但进度圈未消失的问题。 - 会话恢复对 running/pending/accepted 空结果统一收敛 -
ConversationResumeSanitizer.isUnfinishedReviewState把accepted且内容为空也视为未完成;嵌套 Agent / Pipeline 进度里的子工具调用若处于running状态,同样被收敛为"上次生成已中断"的错误结果,避免恢复后仍显示运行中。
- 删除
HttpServerTool- 移除内置工具http_server及其SimpleFileServer实现,包括MainCoordinator.onDestroy中的HttpServerTool.stopActiveServer()调用。 - 清理注册与分类 -
BuiltInToolProviders、ToolSettingsRepository、ToolCategory、ToolDisplayResolver、ToolDisplayCategory、MainDependencies、AgentExecutionController.isAgentToolAllowed中全部移除HttpServerTool相关引用与HTTP显示分类;删除HttpToolCallViewFactory。 - 提示词与文案同步 -
ToolPromptRenderer、执行模式描述字符串、README.md/README_CN.md/CLAUDE.md/simple.md中不再把 HTTP 服务器列为本地/SSH 模式差异点;移除tool_call_block_http字符串。
ToolSettingsRepository分组模式调整 -phone_control工具组由MODE_LOCAL改为MODE_ALL,SSH Shell / 终端提供者模式下也可使用手机控制工具。- 提示词补充说明 -
ToolPromptRenderer在 SSH / 终端提供者工具提示末尾追加"当会话模式为 Control 时,手机控制工具仍然可用"。
- 消息默认 padding 恢复 -
UserMessageView/AssistantMessageView在构造时保存默认 padding,新增restoreDefaultPadding()。 - 多选样式不再强制清零 -
ChatMessageListView.MessageAdapter.applyMultiSelectStyle在非多选/未选中状态下调用restoreMessagePadding恢复默认边距,仅选中消息保留 4dp 描边内边距;修复非多选模式下对话消息贴到屏幕边缘的问题。
- 新增
ToolArgsCleanerTest(124 行)覆盖空输入、Markdown 围栏、单行/多行注释、字符串内注释保留、对象/数组尾部逗号、单引号对象、控制字符、合法 JSON 不变、嵌套尾部逗号等场景。 - 扩展
ConversationResumeSanitizerTest(+121 行)覆盖running非空内容、pending空内容、accepted空内容、嵌套 Agent running 工具调用、嵌套 Pipeline running 工具调用五种恢复收敛场景。 - 更新
ToolSettingsRepositoryTest/AgentExecutionControllerTest断言,适配 HTTP 服务器移除与提示词调整。
- 版本号升级到
1.2.1 versionCode升级到24
- 生命周期钩子补全 -
MainUiController新增onEnterBackground()回调;MainActivity.onPause在super.onPause()之前调用presenter.onEnterBackground(),经MainCoordinatorDelegates转发到delegateView().hideOverlays(),在应用切到后台时统一收起所有浮层。 - 斜杠命令弹窗后台清理 -
ComposerView.dismissSlashPopup()由private提升为public,并在MainChatView.hideOverlays()中调用;修复 1.1.8 引入的SlashCommandPopup在输入框含/文本时切后台不 dismiss,导致 Window Token 失效回前台后整屏黑屏的问题。
StringUtils.decodeUnicodeEscapes- 新增cn.lineai.util.StringUtils.decodeUnicodeEscapes,把 Java 风格\uXXXX转义解码为对应字符;仅解码严格匹配\u后接 4 位十六进制(0-9a-fA-F)的片段,不完整的\u与 Windows 路径(\Users)等原样保留,避免误伤正常内容。- 聊天内错误文本解码 -
GenerationFlowController.failGeneration在错误文本进入ChatMessage、渲染到聊天前统一decodeUnicodeEscapes,覆盖模型通信失败、流式输出失败、HTTP 404/500 等所有聊天内错误展示;describeException对异常 message 同样解码,覆盖工具执行等错误文本。 - SSE 流式错误乱码修复 -
OpenAiCompatibleProtocol新增describeError(Object),当 SSE 返回error为 JSON 对象时优先读取message/type/code字段(不再触发JSONObject.toString()把中文转义成\uXXXX),并对结果兜底解码,修复流式错误在聊天里显示为一串\u转义符的问题。
- 超大负载截断脱敏 -
ErrorLogRedactor新增MAX_SAFE_LENGTH = 1MB上限,输入超过该长度时先取前缀脱敏、剩余以\n... [REDACTED_TRUNCATED]标注丢弃;避免模型协议层在记录含大段 base64 的错误响应时对几十 MB 字符串反复replaceAll复制导致OutOfMemoryError(峰值内存由数十 MB 降为恒定 ~2MB,峰值内存不再随日志体膨胀)。
- 列表项点击勾选 -
ChatMessageListView的ListView新增OnItemClickListener,多选模式下点击消息即切换该条目的选中态(调用toggleSelection),无需仅依赖操作条按钮。 - 选中态高亮描边 -
MessageAdapter.applyMultiSelectStyle在多选模式下为已选中消息绘制LineTheme.ACCENT圆角描边(roundedStroke12dp)+ 4dp 内边距;multiSelectMode/selectedMessageIds下沉到 adapter,随enterMultiSelectMode/exitMultiSelectMode/toggleSelection同步,逐条bind时应用样式。 - 底部操作条避让 - 进入多选模式时
listView底部追加MULTI_SELECT_BAR_EXTRA_PADDING(64dp)内边距,退出时还原,避免底部多选操作条遮挡最后一条消息。
ErrorLogRedactorTest.redactsLargePayloadWithoutOom- 验证 200 万字符超大输入不再 OOM,且头部 secret(Authorization)与长 base64 仍被脱敏、并标记[REDACTED_TRUNCATED]。StringUtilsTest- 新增cn.lineai.util.StringUtilsTest,覆盖基础\u解码、纯文本不变、不完整转义保留、Windows 路径不误解码、null/短输入、混合内容共 6 例。
QuoteController纯逻辑控制器 - 新增cn.lineai.mvp.QuoteController,持有引用文本与预览接口QuotePreview(showQuote/hideQuote),提供setQuote/clearQuote/hasQuote/composeWithQuote;composeWithQuote自动把引用拼成"> ..."块再插入用户输入并清空,发送时一次完成。setQuote文本超过 80 字符自动截断为预览。ComposerView引用预览条 -ComposerView实现QuotePreview,在输入框上方构建圆角描边的引用预览条:左侧 3dp 宽LineTheme.ACCENT竖线、中间预览文本 2 行END省略、右侧 28dpIconButtonView.CLOSE关闭按钮;通过QuoteDismissListener在关闭时通知QuoteController.clearQuote。- 引用文本解析与渲染 -
UserMessageView在bind时解析"> quoted\n> lines\n\nactual"格式,把引用部分抽到quoteTextView单独渲染(最多 3 行省略),主消息文本只保留后半段;空引用时自动隐藏引用条,避免在历史消息上误显示引用块。 - 多选分享模式 -
ChatMessageListView新增multiSelectMode/selectedMessageIds/MultiSelectListener;buildMultiSelectBar在底部构建高 8dp 浮起的操作条(选中计数 + 导出按钮 + 关闭按钮);MessageActionBarView新增MultiSelectButton(IconButtonView.CHECK_SQUARE)入口;enterMultiSelectMode/exitMultiSelectMode切换模式并清空选择。 - 多选消息转
ChatMessage列表 -ChatMessageListView.getSelectedMessages通过adapter.getVisibleMessages过滤选中 id 输出完整消息列表,供ShareController.showFormatPicker复用导出流程。 - 多选发送队列 -
ComposerView在流式生成期间允许输入;发送按钮三态:流式 + 有内容 → 橙色IconButtonView.ARROW_UP追加排队、流式 + 无内容 + 有队列 → 橙色停止、流式 + 无内容 + 无队列 → 红色停止;render监听wasStreamingBefore && !streaming自动post(sendPending),把队列消息在 AI 停下的瞬间继续发送。 MessageActionBarView拆分接口 -Listener重构为ActionListener(onCopy/onQuote/onShare)+SelectListener(onSelect/onMultiSelect)+RecallListener(onRecall)三组接口;新增IconButtonView.SHARE/QUOTE/TEXT_CURSOR/CHECK_SQUARE4 个图标常量与对应ic_lucide_share_2/ic_lucide_quote/ic_lucide_text_cursor/ic_lucide_check_square矢量图。MessageActionListener接口扩展 - 新增onQuoteMessage/onShareMessage/onSelectText/onMultiSelectToggle四个回调;AssistantMessageView/UserMessageView同步绑定到setActionListener+setSelectListener+setRecallListener,streaming构造参数时setActionsVisible(false)隐藏引用/分享/选中/多选按钮。
ExportFormat/ExportResult抽象 - 新增cn.lineai.share.ExportFormat接口(displayName/execute)与cn.lineai.share.ExportResult不可变结果类,支持ACTION_SHARE_FILE(带File+mimeType+Uri)/ACTION_CLIPBOARD(带content)/ACTION_SHARE_TEXT(带content)三类动作。ExportFormatResolver解析器 - 默认注册 5 种格式:ClipboardFormat/PlainTextFormat/MarkdownFormat/PdfFormat/ChatImageFormat;getDisplayNames/get/size供ShareController.showFormatPicker弹窗消费,register允许扩展。PlainTextFormat/MarkdownFormat- 纯文本格式用【我】/【AI】标签分段、末尾追加FOOTER_PLAIN = "—— 来自 LineCode Pro";Markdown 格式用##二级标题 +---分隔 +FOOTER_MD = "*—— 来自 LineCode Pro*"。ChatMessages.toPlainText/toMarkdown静态方法支持单元测试直接构造。ChatImageFormat+ChatBitmapRenderer- 用ChatLayout.measure阶段按 28sp 字体 +IMG_WIDTH=720测每行宽度算出总高,再用ChatCanvas.draw在0xFF1E1E2E背景上按"我"/"AI"角色绘制深浅气泡(0xFF3B3B5C/0xFF2A2A3E圆角 24)+ LTGRAY 角色名;最终Bitmap.compress(PNG, 100)写入cache/share/chat_screenshot.png。PdfFormat+PdfRenderer- 自实现 A4(595×842pt)PDF 渲染:标题 + 正文双TextPaint,每行按measureText自适应宽度自动换行,遇\n强制断行,遇页底finishPage+startNewPage;最终由PdfExporter.save写入cache/share/,再通过ShareFileProvider.uriFor转content://URI。ChatMessages.wrapText通用换行 - 用Paint.measureText在指定maxWidth内逐字符测量,超过则回退到上一换行点;保留原始\n,跳过段落间尾随空白,避免切到字符中间。ShareController调度中心 - 构造注入ExportFormatResolver;showFormatPicker弹AlertDialog列出displayNames,选择后调用format.execute并按ExportResult.action派发到ShareHelper.shareFile/ShareHelper.copy/ShareHelper.shareText;ClipboardFormat在文本 > 5000 字时shouldWarn提示"内容较长,仅部分可能被复制"。
- 合并转发多选 + 格式选择 -
MainChatView.showMultiSelectDialog弹setMultiChoiceItems多选列表(每行[角色] 前 50 字),预选中长按触发的position;showMergeFormatDialog提供 5 种导出:对话截图 / PDF / Markdown / 纯文本分享 / 复制到剪贴板,分别走shareAsChatImage/shareAsPdfWithName/shareAsFile/Intent.ACTION_SEND/ClipboardManager.setPrimaryClip。 - AI 取名文件名 -
askFileNameAndShare弹自定义圆角卡片布局(深色卡片 + 提示文字 + 输入框 + "AI 取名"胶囊按钮),AI 取名按钮调用generateSmartFileName:从首段有效内容(去^[#>*\-\s]+头,长度 ≥ 4 截到 20 字)抽取文件名,缺省回退到chat_<时间戳末 4 位>;最后用name.replaceAll("[/\\\\:*?\"<>|]", "_")清洗非法字符再拼上后缀。 - PDF / 对话截图生成器(
MainChatView内部版) - 独立的shareAsPdfInternal用PdfDocument+ 双Paint手动绘制 A4 页面,分页阈值pageHeight - margin;shareAsChatImage用wrapText+Paint.measureText二次测量得到真实换行结果,再画左右气泡(用户右侧0xFF3B5998、AI 左侧0xFF2D2D44)+ 深色背景 + 居中页脚—— 来自 LineCode Pro。 ShareFileProvider(cn.lineai.log) - 全新自定义ContentProvider(authority<applicationId>.fileprovider)替代ShareFileProvider(cn.lineai.share),提供getType(按扩展名返回application/octet-stream/application/pdf/image/png/text/plain)、openFile(只读 + 规范化路径防穿越 + 文件存在校验)、query(返回OpenableColumns.DISPLAY_NAME+SIZE的MatrixCursor,QQ/微信读取文件前会先query)、insert/update/delete全部禁用。uriFor用new Uri.Builder().scheme("content").authority(...).appendPath(name)拼装 URI。- 悬浮窗"再发"按钮 -
launchShareIntent启动分享 chooser 后延迟 6 秒postDelayed(showFloatingShareButton),使用WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY弹出 3 键悬浮条("再发"紫色 + "返回"灰色 + "关闭");无悬浮窗权限时弹Settings.ACTION_MANAGE_OVERLAY_PERMISSION引导页;onWindowFocusChanged(hasWindowFocus=true)时自动清理悬浮窗与pendingShareFile。 MainChatView长按多选入口 -messageListView.setOnItemLongClickListener触发MultiSelectListener.onMultiSelectTriggered(position),弹showMultiSelectDialog(position)时预选该位置。- 长按文字选中 -
MainChatView.triggerTextSelection用EditText.setKeyListener(null) + setTextIsSelectable(true) + selectAll()构造只读可复制的对话框,规避setTextIsSelectable在聊天项内拦截兄弟按钮触摸事件的问题(同步在UserMessageView/MarkdownTextBlockView注释中明示)。 - 复制逻辑统一 -
MainChatView.copyMessage改用ShareHelper.copy,与导出格式共享同一份ClipboardManager.setPrimaryClip("chat", text)实现。
- 独立
SecuritySettingsScreenView页面 - 新增cn.lineai.ui.component.SecuritySettingsScreenView extends ScreenScaffoldView,拆出"HTTPS 与 HTTP 限制"+"浏览器 JavaScript"两个分区;ScreenFactories.SecuritySettingsScreenFactory注册screenId = "security",由SettingsScreenView改为点击跳转到该新页面。 UrlPolicy放宽模式 - 新增volatile relaxedHttpEnabled静态开关 +setRelaxedHttpEnabled/isRelaxedHttpEnabled访问器;normalizeHttpOrHttpsUrl/normalizeBrowserUrl/requireHttpOrLocalCleartextUrl/isHttpOrLocalCleartext四处在原isAllowedCleartextHttpHost校验之前先判断relaxedHttpEnabled,开启时任意http://与https://一律放行。network_security_config.xml调整 -base-config由cleartextTrafficPermitted="false"改为"true"(让任意 http 请求至少能进到应用层),通过注释明确"cleartext 控制交由cn.lineai.security.UrlPolicy而非此处",避免误以为系统层关闭。OutputSettings持久化字段 - 新增allowAnyHttp字段(isAllowAnyHttp/setAllowAnyHttp),由OutputSettingsRepository读写;SettingsManagementController透传onAllowAnyHttpChanged回调到OutputSettingsController,最终调用UrlPolicy.setRelaxedHttpEnabled。minSdk升级到 26 -app/build.gradle.kts.defaultConfig.minSdk从 24 提升到 26,与OutputSettings持久化、安全设置页、TYPE_APPLICATION_OVERLAY等新 API 对齐。
LineCodeDatabaseBackup自动备份 - 新增cn.lineai.data.db.LineCodeDatabaseBackup,单线程ExecutorService串行化备份任务,目录context.getDir("backups", MODE_PRIVATE)/linecode/,文件backup-<timestamp>.json+latest.json(固定文件名),最多保留MAX_BACKUPS = 3份(pruneOldBackups按时间戳删旧)。saveAsync失败吞异常,绝不抛到主流程。LineCodeDatabaseArchive.exportFullSnapshot- 与现有exportSnapshot(脱敏空 messages 正文)并列新增"完整导出"方法,遍历TABLES时对TABLE_MESSAGE_TEXT_CHUNKS表调用专用exportMessageTextChunksTable,其他表复用exportTable,输出 JSON 携带"full": true标记;exportSnapshot与exportFullSnapshot共享LineCodeArchiveCodec.ENTRY_DATABASE文件名。LineCodeDatabaseErrorHandler自定义损坏处理 - 实现DatabaseErrorHandler替换DefaultDatabaseErrorHandler:onCorruption走"复制为.corrupted-<timestamp>存档 → 写入.needs-restore标记 → 删除损坏库文件"三步,全部try/catch Throwable吞异常,避免向上抛出二次崩溃。needs-restore自动恢复 -LineCodeDatabase.onOpen新增maybeRestoreFromBackup:LineCodeSchema.DATABASE_NAME + ".needs-restore"标志存在时调用LineCodeDatabaseBackup.restoreLatest(this)把latest.json数据导入当前空库(LineCodeDatabaseArchive反序列化),恢复成功/失败均删除标志,保留空库兜底。integrityOk用PRAGMA integrity_check(1)启动期自检;backupAsync公开方法供ConversationRepository在事务setTransactionSuccessful之后异步触发一次。ConversationRepository事务后自动备份 -appendMessages在db.endTransaction()后调用database.backupAsync(),保证每次成功落库后 6 个提交窗口内都有可用备份,应对系统杀死进程导致的库损坏。
ToolDisplayCategory枚举 - 新增cn.lineai.tool.ToolDisplayCategory(READ/WRITE/DELETE/SHELL/AGENT/AGENT_PIPELINE/TODO/IMAGE_GENERATION/PHONE_CONTROL/HTTP/GENERIC),把工具显示路由从 UI 字符串判断改为枚举。ToolDisplayResolver解析器 - 新增cn.lineai.tool.ToolDisplayResolver取代ToolCallUtils的字符串散落判断,方法:getDisplayCategory(name)(优先用ToolRegistry.getCachedDisplayCategory,缺省走fallbackDisplayCategory覆盖file_read/glob/list_dir/web_search/web_fetch/image_understanding→READ、file_write/file_edit→WRITE、file_delete→DELETE、http_server→HTTP、shell_execute→SHELL、agent/agentx_→AGENT、agent_pipeline→AGENT_PIPELINE、todo_update→TODO、image_generation→IMAGE_GENERATION、phone_*→PHONE_CONTROL、mcpx_→GENERIC)、getDisplayLabel/getActionName直接从BaseTool拿。静态setDefault/getDefault提供全局默认实例。ToolCallCardView统一接口 - 新增cn.lineai.ui.component.toolcall.ToolCallCardView接口(setToolReviewListener/setProjectPath/bind(ToolCall, ToolResult)),让ToolCallBlockView不再依赖具体子类型(之前对ToolCallWriteView/ToolCallDeleteView/ToolCallReadView/ToolCallShellView/ToolCallTodoView/ToolCallAgentView/ToolCallAgentPipelineView一连串instanceof判断)。ToolCallViewFactory+ToolCallViewFactoryRegistry- 新增cn.lineai.ui.component.toolcall.ToolCallViewFactory(createView(Context) -> ToolCallCardView),内置ReadToolCallViewFactory/WriteToolCallViewFactory/DeleteToolCallViewFactory/ShellToolCallViewFactory/TodoToolCallViewFactory/AgentToolCallViewFactory/AgentPipelineToolCallViewFactory/HttpToolCallViewFactory/ImageGenerationToolCallViewFactory/PhoneControlToolCallViewFactory/GenericToolCallViewFactory11 个实现。ToolCallViewFactoryRegistry按ToolDisplayCategory注册工厂,createView(Context, category)返回对应ToolCallCardView。ToolCallBlockView简化渲染 - 把 100+ 行if/else instanceof链替换为REGISTRY.createView(ctx, ToolCallUtils.getDisplayCategory(name))+childView.setToolReviewListener+childView.setProjectPath+addView(childView)+childView.bind5 行;setToolReviewListener/setProjectPath也改用统一的ToolCallCardView接口。NestedToolCallParser嵌套工具调用解析 - 新增cn.lineai.tool.NestedToolCallParser.parse(JSONArray) -> List<NestedCall>,把 Agent / Pipeline progress 数组中{"id", "name", "arguments", "result": {...}}解析为NestedCall(call, result),ToolCallAgentView/ToolCallAgentPipelineView不再内嵌 JSON 解析逻辑。
- UI 模型类独立包 - 新增
cn.lineai.model下 6 个 UI 层不可变数据类:ConversationUiModel/DiffUiModel/ExtensionItemUiModel/ExtensionKindUiModel/KeepAliveSettings/StorageStatsUiModel,把Conversation/DiffRecord/ExtensionItem/ExtensionKind/KeepAliveSettings(数据层原定义)等实体映射为 UI 专用模型,View 层只接收 UI 模型。 ExtensionActionCallback回调接口 - 新增cn.lineai.mvp.ExtensionActionCallback(onSave/onDelete/onTest等),把扩展详情页的操作从 View 直接调用 Repository 改为回调到 Coordinator,View 不再依赖 Repository。DiffLoader接口 - 新增cn.lineai.ui.component.toolcall.DiffLoader(loadDiff(diffId) -> DiffRecord),由 Controller/Assembler 实现,注入到ToolCallWriteView,View 层不再直接持有DiffRepository。CardViewHelper圆角卡片工具 - 新增cn.lineai.ui.component.CardViewHelper,统一封装"圆角背景 + padding + 标题 + 描述"组合,被多个 Screen 复用,删除ExtensionDetailScreenView等页面内重复的卡片段。StringUtils字符串工具 - 新增cn.lineai.util.StringUtils,提供空值 / 截断 / 路径安全 / 字符计数等纯函数,被多个 Repository 复用。SkillFrontmatterParser+SkillFileManager+SkillPromptBuilder- 把SkillRepository中"读 frontmatter + 文件管理 + prompt 拼装"三段混在一起的代码拆为 3 个独立类:SkillFrontmatterParser解析 YAML frontmatter(SkillPromptBuilder装配系统提示词、SkillFileManager负责文件 IO + 缓存)。SkillRepository内部行数从 665 减少到 ~50,只剩数据库 CRUD。ModelRepositorySQLite 迁移 - 新增cn.lineai.data.repository.ModelRepository implements ModelStore:ensureModelConfigColumns自检并补齐model_configs表列;migrateLegacyPreferencesIfNeeded检测linecode_modelsSharedPreferences 中的sqlite_migrated标记,未迁移时把KEY_MODELSJSON 数组和KEY_SELECTED_ID一次性导入 SQLite;之后getModels/getModel/save/deleteModels/setSelectedModelId/getSelectedModel/clearAll全部走 SQLite(ORDER BY selected DESC, updated_at DESC)。ToolSettingsScreenView默认模式硬编码修复 - 之前默认执行模式硬编码为null,改为从ToolSettingsRepository.getDefaultExecutionMode()读取,避免初次安装后界面显示空白。ComposerView等视图成员变量可修改 -ComposerView/DrawerView/KeepAliveSettingsScreenView等视图的成员变量从final改为非final,便于子类扩展与运行时切换。
ModelProtocol默认方法 -ModelProtocol接口新增supportsNativeTools()/supportsContextCompaction()/supportsImageGeneration()/supportsImageUnderstanding()4 个default方法返回true;AnthropicMessagesProtocol/CodexResponsesProtocol/LocalGgufProtocol/OpenAiCompatibleProtocol按需覆写其中部分为false,调用方代码从if (protocol instanceof ...)改为if (!protocol.supportsXxx())。ReasoningRequestStrategy推理策略 - 新增cn.lineai.ai.protocol.ReasoningRequestStrategy接口(matches(baseUrl, modelId)+apply(JSONObject body, ReasoningRequestContext context))与ReasoningStrategyRegistry(按顺序注册、按matches找到第一个命中的策略)。OpenAiCompatibleProtocol把原来硬编码的if (url.contains("deepseek"))等分支改为遍历 registry;新增DefaultReasoningStrategy(matches始终返回true兜底)/DeepseekReasoningStrategy/DashscopeReasoningStrategy/MoonshotReasoningStrategy/MinimaxReasoningStrategy5 个实现。- 多厂商推理支持 - 实现了
DeepseekReasoningStrategy(baseUrl命中deepseek时在请求体加reasoning_effort字段)、DashscopeReasoningStrategy(baseUrl命中dashscope.aliyuncs时加enable_thinking+thinking_budget)、MoonshotReasoningStrategy(baseUrl命中moonshot时加reasoning_content字段)等。ReasoningRequestContext携带enabled/effort/preserveReasoning/baseUrl/modelId/thinkingBudget全部上下文,避免在每个策略里重新拼装。 - Web 搜索多提供商 - 新增
cn.lineai.tool.builtin.WebSearchProvider接口(providerId+buildRequest+normalizeResults)+WebSearchProviderRegistry(注册 + 按providerId取出);实现BingSearchProvider/BraveSearchProvider/SerpApiSearchProvider/TavilySearchProvider/DefaultSearchProvider/QueryCountSearchProvider6 个。WebSearchService原本 160+ 行if (provider.equals(...))重构为注册表查找 + 通用HttpRequest调度;SearchRequest与SearchResultItem数据类明确请求/响应契约。 - 扩展管理策略模式 - 新增
cn.lineai.mvp.ExtensionKindDescriptor抽象接口 +ExtensionKindRegistry注册表 +AgentKindDescriptor/McpKindDescriptor/LinecodeKindDescriptor/SkillsKindDescriptor4 个实现。ExtensionManagementController/ExtensionDetailScreenView把if (kind == AGENT) ... else if (kind == MCP) ...链条改为遍历注册表 +descriptor.canHandle(item)分发,新增扩展类型只需注册 descriptor,不再动业务代码。 - Agent 角色提示词模板 -
assets/prompts/新增 5 个 Agent 模板:agent-role-coding-local.txt/agent-role-coding-remote.txt(编程型 Agent 区分本地/远端 shell 模式)、agent-role-explore-local.txt/agent-role-explore-remote.txt(探索型 Agent 同样区分)、agent-system-prompt-template.txt(系统提示词主模板,含{{ROLE_PROMPT}}/{{TASK_DESCRIPTION}}/{{WORKSPACE_CONTEXT}}/{{SCOPE_CONTEXT}}/{{EXTENSIONS_CONTEXT}}/{{TOOLS_CONTEXT}}占位符)。PromptTemplateRepository新增getTemplateText(id)读取方法。 - 流式渲染独立控制器 - 新增
cn.lineai.mvp.StreamingRenderController把流式渲染的缓冲 / 调度 / 状态机从GenerationFlowController拆出来,便于针对 streaming 路径做单元测试与扩展。
BaseTool.NAME常量 - 25 个内置工具(FileReadTool/FileWriteTool/FileEditTool/FileDeleteTool/GlobTool/ListDirectoryTool/HttpServerTool/ImageGenerationTool/ImageUnderstandingTool/ImageResponseParser/PhoneClickTool/PhoneClickViewTool/PhoneLongPressTool/PhoneSwipeTool/PhoneGlobalActionTool/PhoneScreenshotTool/PhoneViewHierarchyTool/ShellExecuteTool/WebFetchTool/WebSearchTool/TodoUpdateTool/AgentTool/AgentPipelineTool/CustomAgentExtensionTool/CustomMcpHttpTool)全部添加public static final String NAME常量;ToolCategory.isReadType/isWriteType/isDeleteType/isHttpType/isShellType/isAgentType/isAgentPipelineType/isTodoType/isImageGenerationType/isImageUnderstandingType/isPhoneControlTool全部从硬编码字符串改为引用常量。所有工具getName()返回NAME,避免工具重命名时漏改一处。BaseTool扩展方法 -requiresConfirmation标记@Deprecated,新增needsConfirmation()(default false)和isAllowedInReadonlyMode()(default false)分别表达"是否需要用户确认"和"在只读模式下是否允许执行";新增promptSupplement(String executionMode, boolean isSsh)(default null)允许工具按执行模式与 SSH 标识补充提示文本,例如ImageUnderstandingTool在 SSH 模式下提示"通过 SFTP 读取 SSH 工作区图片"。ToolResult快捷工厂 - 新增static success(output)/error(error)/withReview(output, toolCallId, toolName, diffId, reviewState, reviewMessage)三个工厂方法,4 个旧构造器标记@Deprecated,调用方从new ToolResult("", "", msg, true)简化为ToolResult.error(msg)。ToolContext依赖注入扩展 - 新增ToolSettingsStore/ModelStore/SshFileTreeStore/ModelProtocolFactory/ModelClient/PromptTemplateRepository6 个可选依赖字段 + 4 个新构造器重载;ToolExecutor在执行工具前调用needsInjection检查并injectDependencies把 Executor 持有的依赖注入到ToolContext,工具不再需要在自己的execute里new ModelRepository(context)。ToolExecutor8 参数构造器 - 新增ToolExecutor(registry, settingsRepository, diffRepository, modelRepository, sshFileTreeRepository, modelProtocolFactory, modelClient, promptTemplateRepository)全量依赖构造器;MainDependencies改为调用 8 参数版,把整套依赖一次注入。ToolRegistry.getCachedDisplayCategory- 新增getCachedDisplayCategory(name)内部缓存Map<String, ToolDisplayCategory>,避免每次getDisplayCategory都重新计算;启动期一次性preload全部内置工具。- 图片生成工具依赖注入修复 -
ImageGenerationTool之前在自己构造时new一堆 repository,dc6d82e改为从ToolContext取toolSettingsStore/modelRepository/modelProtocolFactory/modelClient/sshFileTreeRepository,与ImageUnderstandingTool对齐;ImageUnderstandingTool同步从Context构造改为ToolContext注入,并新增promptSupplement在 SSH 模式返回 "SFTP 读取图片" 提示。 WebSearchTool环境提示 -WebSearchTool.getDescription末尾追加"环境补充:搜索结果中给出的 URL 必须在web_fetch之前先用UrlPolicy校验"提示,提醒模型筛选可用 URL。- 部分工具 readonly / confirmation 标识 -
FileReadTool/ListDirectoryTool标记isAllowedInReadonlyMode = true(只读模式下仍允许执行);FileWriteTool/FileEditTool/FileDeleteTool/ShellExecuteTool/WebSearchTool等写操作工具标记needsConfirmation走原requiresConfirmation路径;ImageGenerationTool/ImageUnderstandingTool标记needsConfirmation由用户在工具设置里决定。 ImageGenerationTool协议工厂修复 - 之前ImageGenerationTool缺少modelProtocolFactory注入导致create(model.getProtocolType())NPE,dc6d82e注入后由ImageResponseParser统一解析图片 URL/Base64。HostBase抽象宿主 - 新增cn.lineai.mvp.HostBase implements CoordinatorHost,把MainCoordinator公共方法(basename/parentPath/projectPath/projectLabel/isSshExecutionMode/isTerminalProviderExecutionMode/showNotice/isViewAttached/viewHideOverlays/viewShowScreen/viewShowChatScreen/refreshVisibleScreen/returnToScreen)抽到HostBase,各 Controller 改为extends HostBase减少样板代码。ErrorLogController/PhoneControlController- 新增两个轻量 Controller,把ErrorLogRepository/PhoneControlRepository暴露给MainCoordinator;ErrorLogController提供list()/clear();PhoneControlController提供isAccessibilityEnabled/isDisclaimerAccepted/isPermissionEnabled/setPermissionEnabled/setDisclaimerAccepted。ToolCallTextParser健壮性 - 内部实现对工具调用文本解析失败时返回空数组而非抛异常;ToolPromptRenderer路径从data/repository移到ai/prompt,与SystemPromptProvider同包。
ChatMessageListView缓存复用重构 - 移除canReturnCachedView与bindCachedView两个内部方法,引入通用obtain(Class<T> type, String key, T created)工具:先查rowCache.get(key),类型匹配且getParent() == null则复用,否则用created替换并putCache;putCache顺手清理旧 view 的tag。模型切换通知的缓存命中后不再调用bind,直接复用convertView。UserMessageView/AssistantMessageView复用判断 -getView中先判断convertView是否同类型实例(UserMessageView/AssistantMessageView),同类型直接setXxxListener+bind复用;不同类型才走obtain路径,避免每条消息都new视图实例触发setToolReviewListener/setProjectPath副作用。MainChatView长按多选入口 -listView.setOnItemLongClickListener把position透传给MultiSelectListener,触发showMultiSelectDialog。MarkdownTextBlockView触摸事件修复 - 删除原setTextIsSelectable(true),通过注释明确"会偷走兄弟按钮的触摸事件,改由TextSelectionDialog弹可选择 EditText"。ComposerView多选发送队列渲染 -render(ChatUiState state)中检测wasStreamingBefore && !streaming && !pendingQueue.isEmpty()时post(sendPending)自动续发;input.setEnabled(true)允许在流式期间继续输入;attachButton仍按streaming灰化。UserMessageView引用块 - 新增quoteBlockView(圆角深色 + 左侧 3dpLineTheme.ACCENT竖线 + 最多 3 行省略的斜体引用文本)作为contentText之上的子视图,宽度限制与主气泡一致;空引用时setVisibility(GONE)隐藏。ChatMessageListView多选模式滚动条控制 -updateScrollToBottomVisibility在multiSelectMode开启时强制隐藏"滚动到底部"按钮,避免遮挡底部操作条;programmaticScroll标志在smoothScrollBy期间抑制"用户主动滚动"判断,避免流式跟随后误关闭followTailEnabled。IconButtonView新增 4 个图标 -SHARE(80) /QUOTE(81) /TEXT_CURSOR(82) /CHECK_SQUARE(83),对应ic_lucide_share_2/ic_lucide_quote/ic_lucide_text_cursor/ic_lucide_check_square4 个矢量图。MainChatView合并转发/AI 取名 UI - 自定义圆角卡片布局:深色0xFF2A2A3E圆角 18 卡片 + "后缀自动添加: .pdf" 灰色提示 +EditText圆角描边输入框(自动 selectAll +inputType=text)+ 紫色0xFF5B4FCF圆角 14 "AI 取名" 胶囊按钮。
- 许可证资源打包方式重构 - 移除
app/src/main/resources/META-INF/LICENSE(674 行)与app/build.gradle.kts中META-INF/resources/META-INF/LICENSE的assets注入配置;新增app/build.gradle.kts自定义generateLicenseCopy任务,把仓库根LICENSE文件自动复制到app/build/generated/assets/license/LICENSE,由processReleaseResources/processDebugResources作为额外inputs.file包含;统一许可证加载来源到根目录文件。 - 移除冗余 COPYING 文件 - 删除仓库根
COPYING副本;同步更新中英文README.md/README_CN.md中对COPYING的引用,统一指向根目录LICENSE作为唯一许可证来源。
- 新增 11 条字符串 -
values/strings.xml与values-zh/strings.xml同步添加:message_action_quote_desc(引用消息)/message_action_share_desc(分享消息)/message_action_select_desc(选中文字)/message_action_multi_select_desc(多选)/dialog_export_format_title(导出格式)/dialog_select_text_title(长按选中文字)/quote_preview_label(引用)/export_button_label(导出)/toast_clipboard_large(内容较长,仅部分可能被复制)。 - 安全设置页文案 -
settings_row_security_allow_any_http_title/settings_row_security_allow_any_http_desc/screen_security_title/screen_security_section_http/screen_security_section_browser5 条新字符串。
- 数据库迁移 -
LineCodeSchema表结构未变,仅在LineCodeDatabase.onOpen启动期增加integrity_check(1)自检与maybeRestoreFromBackup恢复,旧数据库直接打开不会丢失数据。 - 旧
ToolSettingsRepositoryAPI 兼容 - 旧调用方通过@Deprecated构造器仍可工作,新代码改用MainDependencies注入的ToolSettingsStore接口。 ModelConfig旧构造器兼容 - 3 个旧@Deprecated构造器(ModelConfig(id, name, protocolType, ..., modelId)等)保留可用;新代码使用ModelConfig.builder(...).toolCallLimit(...).compressionModelEnabled(...).build()链式构造。
- 版本号升级到
1.1.9 versionCode升级到22minSdk升级到26
- 新增
QuoteControllerTest(94 行)覆盖setQuoteStoresText/composeWithQuotePrefixesQuote/composeWithQuoteClearsAfterSend/composeWithoutQuoteReturnsInputUnchanged/clearQuoteRemovesQuote/setQuoteNotifiesPreview/clearQuoteHidesPreview/longQuoteIsTruncatedInPreview等用例 - 新增
ChatMessagesTest(41 行)覆盖toPlainText/toMarkdown/wrapText三种格式的转换与换行 - 新增
ExportFormatResolverTest(49 行)覆盖默认注册顺序 /register扩展 /get/size/getDisplayNames行为 - 新增
ExportResultTest(32 行)覆盖forFile/forClipboard/forShareText三种 action 的字段填充 - 扩展
AgentExecutionControllerTest(+52 行)覆盖dc6d82e引入的isAllowedInReadonlyMode/needsConfirmation/promptSupplement(executionMode, isSsh)三组新方法 SlashCommandCatalogTest之前用例保持通过- 已验证
./gradlew :app:testDebugUnitTest/./gradlew :app:lintDebug/./gradlew :app:assembleDebug/./gradlew :app:assembleDebugUserCert
- 斜杠命令系统 - 聊天 composer 中输入
/触发命令弹窗,按键入内容实时过滤候选项;支持主命令(/chat、/plan、/agent、/control、/model)、模型 id 补全与思考等级选择,点击候选项自动回填为完整命令文本 SlashCommandCatalog解析与过滤 - 新增cn.lineai.ui.util.SlashCommandCatalog纯逻辑工具类,提供MAIN_COMMANDS/REASONING_LEVELS常量、filterMain/filterModelIds/filterReasoningLevels前缀过滤、parse整段文本解析为Kind.MODE或Kind.MODEL;不依赖 Android 视图,便于 JUnit 覆盖SlashCommandPopup组件 - 独立实现 composer 上方展示的命令弹窗:圆角描边、行高紧凑化(标题 22dp)、/前缀加 ACCENT 色 + BOLD 加粗、当前态圆点指示;show在title+rows数量未变时跳过重建,showAtAnchor自动对齐到 anchor 容器并向上 8dp 弹出/标签着色 -SlashCommandPopup.formatLabel把以/开头的 token 第一个空白前的部分加ForegroundColorSpan(ACCENT)+StyleSpan(BOLD),弹窗中/chat、/model等命令一眼可辨- 点击回调主线程投递 - 行
OnClickListener改为new Handler(Looper.getMainLooper()).post(onClick),避免 popupdismiss()与点击动作同帧触发的竞态 - 发送时拦截斜杠命令 -
ComposerView.handleSendClick在 send 时调用SlashCommandCatalog.parse;命中MODE时走Listener.onModeChanged,命中MODEL时同时调用onModelQuickSwitch与可选的onAiReasoningEffortChanged;未命中时按原逻辑走onSend - 多语言文案 -
values/strings.xml与values-zh/strings.xml新增slash_command_main_title/slash_command_model_title/slash_command_reasoning_title以及 4 种模式、5 档思考等级的副标题,弹窗描述根据语言自动切换 - 流式生成时禁用 -
setStreaming在生成期间关闭并清理slashPopup,避免与现有 model / mode 弹窗互相干扰
- 子 Agent 工具审核流程 -
AgentExecutionController.executeAgentToolCallWithReview在awaitReview之前调用新增的host.requestAgentToolReview(displayToolCallId, call, pending),主流程感知到pending审核态后立即持久化并render;finally块保证在执行完成、被拒绝或被中断时调用host.clearAgentToolReview清理 - 拒绝结果落库 - 拒绝分支不再直接返回新建的
ToolResult,而是同步调用progress.putToolResult+host.addOrReplaceToolResult(progress.snapshotResult()),让 UI 在拒绝时立刻看到rejected状态卡片 AgentProgressSession.snapshotResult透传状态 - 由new ToolResult(..., error)调整为new ToolResult(..., error, "", status, ""),把pending/running/done/error等内部状态写进外层ToolResult.reviewStateGenerationFlowController跟踪待审核请求 - 新增pendingAgentToolRequests映射与requestAgentToolReview/clearAgentToolReview/isPendingAgentToolReview/acceptAgentToolReview入口;cancelActiveGeneration同步清空;MainCoordinatorDelegates.handleToolReview在收到审核回调时优先尝试 agent 路径- UI 审核态判断扩展 -
ToolCallAgentView读取result.getReviewState(),与 progress status 任一为pending时都视为待审核;pending卡片稳定显示,避免审核期间闪烁
- 会话级自动确认 -
AgentExecutionController.executeAgentToolCall在工具需要确认时先调用toolReviewAwaiter.isAutoConfirmed(call);命中则直接走toolExecutor.executeConfirmed,跳过awaitReview阻塞与 UI 审核面板 ToolReviewAwaiter接口扩展 - 新增boolean isAutoConfirmed(ToolCall call)默认返回false的方法,由主流程在初始化setToolReviewAwaiter时实现并与MainCoordinator.sessionAutoConfirmedTools联动- 工具调用 UI 视图复用 -
ToolCallBlockView对ToolCallAgentView/ToolCallAgentPipelineView/ToolCallAgentView(自定义 Agent)三类子视图在bind前先getChildAt(0)复用已有实例,避免每次刷新都重新new并触发setToolReviewListener/setProjectPath副作用 - Todo 行高自适应 -
ToolCallTodoView将固定rowHeight改为minRowHeight,通过setMinimumHeight实现最小 28dp + WRAP_CONTENT,长任务描述能自然撑高而短条目仍维持原视觉
- 总时长预算替代最大轮次 - 移除
AGENT_MAX_TURNS = 8硬轮次上限,新增AGENT_TOTAL_BUDGET_MS = 30 分钟;runAgentLoop把for (turn = 0; turn < 8)改为while (true),由取消 / 工具次数限制 / 时间预算三种条件共同决定退出,避免深度任务被 8 轮卡死 - 工具调用次数共享预算 -
GenerationFlowController.toolContext透传usedToolCallCount到AgentRunner,runAgentTool/runAgentPipelineTool在调用入口构造int[] toolCallBudget;Agent / Pipeline / Pipeline 内部子 Agent 每次工具调用都toolCallBudget[0]++,跨调用共享模型配置的toolCallLimit - 超过预算安全退出 -
runAgentLoop在每轮入口与执行工具前检查toolCallBudget[0] >= toolCallLimit,命中返回AGENT_TOOL_LIMIT_MESSAGE("Agent 已达到主流程总工具调用次数上限。")并把 progress 同步到error状态;Pipeline 收到含该消息的子结果立即中断后续层并写入错误摘要 - 时间预算检查 - 同样在每轮入口检查
System.currentTimeMillis() - startedAt > AGENT_TOTAL_BUDGET_MS,命中返回带"最后输出"的超时消息;Pipeline 整体pipelineBudgetMs = agents.size() * AGENT_TOTAL_BUDGET_MS在每个 level / agent 进入前双重判断 - 取消与初始检查 -
runAgentTool/runAgentPipelineTool入口增加cancellationToken.isCancelled()提前返回;Pipeline 在外层循环与每个 agent 进入前各检查一次取消与时间预算 - Pipeline 进度汇总落库 -
PipelineProgressSession新增setStatus/setFinalSummary/getFinalSummary/payload公共方法与ProgressPublisher接口;runAgentPipelineTool在最终/异常分支统一调用pipelineProgress.setFinalSummary+setStatus+publish(true)+addOrReplaceToolResult,让 UI 在流水线结束时能直接拿到 summary - 远端 Shell 模式提示词 -
agentRolePrompt/agentWorkspacePrompt/agentScopePrompt新增boolean remoteMode重载;SSH 或终端提供者模式下返回"远程 Shell"专用提示词:明确file_read / file_write / file_edit / glob / list_dir不一定可用、必须通过shell_execute完成探查与写入、禁止调用写操作类工具;探索 Agent 进一步禁止任何有副作用的命令
- 读取超时延长到 10 分钟 -
AbstractHttpModelProtocol.openConnection把setReadTimeout(120000)调整为setReadTimeout(600000),匹配 Agent 30 分钟总预算下的长流式响应与 reasoning 内容;避免大输出 / 慢模型在 2 分钟后被强行断开 - Connection: close 头 - 显式设置
Connection: close请求头,避免长 keep-alive 在 NAT / 代理环境下被中间设备单边切断导致首包延迟或半包
- 参数解析失败专用卡片 -
ToolCallAgentPipelineView在bind时调用parseInputError检查模型原始参数;JSON 解析失败或输入为空时直接渲染bindParseError视图(标题、红色CIRCLE_X状态、错误描述),不再误显示空 agents 列表 - 最终 summary 单独展示 -
progress.optString("summary")在 agents 为空时通过分割线 +MarkdownView单独渲染,便于查看流水线终止原因
- 标题紧凑化 -
titleParams高度由 32dp 改为 22dp,margin 从底部XS调整为顶部 1dp,弹窗整体更紧凑 - 行间距 - 容器 vertical padding 由 0 改为
LineTheme.SM,描述行顶部 margin 1dp,行间层次更清晰
- 版本号升级到
1.1.8 versionCode升级到21
- 新增
SlashCommandCatalogTest(134 行)覆盖filterMain空查询返回全部 / 大小写不敏感前缀匹配 / 未知前缀返回空、parse模式命令解析、/model必填 id 与可选思考等级、无效思考等级保留 id、未知命令与/model缺 id 返回 null - 扩展
AgentExecutionControllerTest:subAgentToolReviewNotifiesMainFlowBeforeAwaiting验证子 Agent 工具审核在 await 之前就触发主流程的requestAgentToolReview并在结束时clearAgentToolReviewsubAgentToolReviewClearsMainFlowAfterReject验证拒绝路径返回rejected状态、错误内容包含"用户拒绝执行"并清理主流程审核snapshotResultPropagatesStatusToOuterReviewState验证 progress 状态变化能正确透传到外层ToolResult.reviewStateshellExecuteAutoConfirmedSkipsReviewAndExecutesConfirmed验证会话级自动确认时不再走awaitReview且不触发主流程审核agentRolePromptSwitchesToShellInRemoteMode验证agentRolePrompt(type, false)提及 file 工具但不出现"远程 Shell",agentRolePrompt(type, true)出现"远程 Shell"、"shell_execute" 与"不一定可用"agentRolePromptExploreInRemoteModeRecommendsShell验证探索型 Agent 在远端模式下提示词同时出现"远程 Shell"与shell_execute
- 已有
shellExecuteWaitsForConfirmationBeforeRunningInsideAgent改名为shellExecuteWaitsForReviewAndResumesOnAccept并补充FakeHost默认实现requestAgentToolReview/clearAgentToolReview/isSshExecutionMode/isTerminalProviderExecutionMode桩方法 - 已验证
./gradlew :app:testDebugUnitTest
- 消息文本分块存储 - 新增
message_text_chunks侧表,把messages.content/reasoning_content/raw_json等大文本按 64KB 切片存放,规避 SQLiteCursorWindow单行 2MB 限制;模型输出或大文件 diff 写入不再因为单行过大而触发SQLiteBlobTooBigException - 数据库版本升级到 4 -
LineCodeSchema.VERSION升到 4,并新增AddMessageTextChunksTable迁移,在onUpgrade时按顺序建表与索引;v3 数据库升级时数据不会丢失 - Repository 适配分块读写 -
ConversationRepository、LearningContextRepository、StorageStatsRepository改为通过MessageTextChunkStore读写大文本;ConversationIndexer写入索引时只保留 4000 字符的摘要,raw_json不再落到conversation_index,避免索引行过大 - 学习上下文兼容 -
LearningContextRepository在读取历史消息和索引时通过substr(..., 320)截取前缀,并通过message_text_chunks兜底读取分块文本;storage_stats中的聊天与 diff 缓存统计改为基于MessageTextChunkStore.totalLength聚合 - .linecode 归档适配分块 -
LineCodeDatabaseArchive导出时把messages表的大文本列置空并在message_text_chunks中按 64KB 切片存放;旧版归档中可能仍包含历史分块文本的兼容逻辑已补齐,新增nullCell/integerCell/stringCell工具方法
- Tool Call 配对修复 -
ModelPromptController.completeToolCallPairsForRequest会在构造模型请求前把缺失的tool消息补齐,避免 assistanttool_calls没有对应结果导致 OpenAI / Anthropic / Responses 协议拒绝请求;同时把游离的tool结果移动到对应 assistant 之后,过期或孤儿的tool消息会被丢弃 - 中断补齐默认文案 -
ModelPromptController.Host新增interruptedGenerationMessage默认方法,中文返回上次生成已中断。、英文返回Previous generation was interrupted.;MainCoordinator通过R.string.message_generation_interrupted覆盖默认文案,保证多语言一致 - 补齐逻辑覆盖 stop / kill 场景 - 用户主动停止生成、应用被强杀、进程重启后,模型请求都会带上补齐后的
tool配对,对外模型不会因缺结果而报错或要求重复工具调用
- 屏幕切换无动画刷新 -
MainChatView.showScreen新增animate重载;invalidateScreen重建当前页时不再播放转场动画,避免数据刷新时的闪烁;ScreenView新增evictScreen默认方法,调用链路更清晰 - 前进 / 返回方向控制 -
ScreenNavigationController.Host.showScreen(id, forward, animate)默认实现转发到showScreen(id, forward),新接口允许在backFrom路径上保留方向感知的反向动画 - 抽屉方向修复 -
DrawerView从顶部面板调整为左侧侧边栏样式:Gravity.START+DrawerWidth 360dp+translationX动画;与 v1.1.6 的描述一致,避免小屏上文件树与会话列表被压缩 refreshVisibleScreen不再误触发动画 -MainCoordinator中两处view.invalidateScreen调用改为view.evictScreen+showScreen(id, true, false),重建当前页时直接落到终态,行为符合直觉
- 版本号升级到
1.1.7 versionCode升级到20
- 新增
ModelPromptControllerTest覆盖:缺失tool结果补齐、已有tool结果重排到 assistant 之后、孤儿tool结果丢弃、空输入不抛异常等场景 - 新增
AddMessageTextChunksTableTest校验迁移目标版本为 4 - 扩展
LineCodeSchemaTest覆盖message_text_chunks表与索引的建表 SQL 声明 - 扩展
ScreenNavigationControllerTest覆盖refreshVisibleScreen无动画重建与backFrom反向动画 - 已验证
./gradlew :app:testDebugUnitTest
- 子 Agent 工具确认机制 - Agent 内部调用需要确认的工具时不再直接失败,而是进入与普通工具一致的待确认流程;Shell、删除等高风险工具会显示等待确认状态,用户确认后继续执行,拒绝后写入拒绝结果
- Agent 进度待确认状态 - Agent 进度 JSON 新增
pending状态展示,卡片中显示“需要确认”,并保留嵌套工具调用、确认状态、执行结果与错误信息,避免等待确认时被误判为运行失败 - Agent Pipeline 待确认展示 - Agent 流水线卡片支持统计和展示子 Agent 的待确认状态;每个 Agent 行可展开显示其内部工具调用,审批按钮与普通工具调用保持一致
- 会话级自动确认延续到 Agent - 子 Agent 内部工具确认支持“本次会话自动执行”,确认策略与普通 Shell 工具一致,减少重复审批
- SSH 连接池锁异常 - 修复 SSH 测试连接和执行命令在输出正确后仍抛出
IllegalMonitorStateException的问题;新建连接会正确持有锁,释放、丢弃和重建连接时只由持锁线程解锁 - 中断后重开进度圈残留 - 修复用户停止生成、直接关闭 APP 或进程被杀后,重新打开会话仍显示进度圈的问题;加载历史会话时会把残留的
streaming、running、pending、缺失 tool result、Agent / Agent Pipeline 运行态统一收敛为“上次生成已中断。”并落库 - Agent / Pipeline 停止状态清理 - 主动停止生成时复用同一套进度清理逻辑,Agent、子 Agent 工具调用、Agent Pipeline 运行态与待确认态都会立即变为错误完成态,避免 UI 继续等待不存在的后台任务
- 屏幕切换动画 - 设置页、模型页、扩展页等二级页面新增前进/返回方向感知动画,返回时使用反向过渡,导航栈状态更清晰
- 抽屉与弹层动画优化 - 优化抽屉、底部操作表、目录选择器、附件选择器的入场和退场动画,关闭时会取消旧动画并复位状态,减少快速切换时的闪烁和残留
- 抽屉布局调整 - 会话/文件抽屉改为更适合移动端的顶部面板样式,并限制高度,文件树与会话列表在小屏上更稳定
- 版本号升级到
1.1.6 versionCode升级到19
- 新增
AgentExecutionControllerTest覆盖子 Agent Shell 工具确认、拒绝、自动确认与权限边界 - 新增
SshConnectionPoolTest覆盖新建连接释放、丢弃重借、陈旧连接移除等锁行为,防止回归到IllegalMonitorStateException - 扩展
ScreenNavigationControllerTest覆盖前进/返回方向传递 - 新增
ConversationResumeSanitizerTest覆盖重启恢复时清理 streaming、pending 工具、缺失 tool result、Agent pending、Pipeline running 等残留状态 - 已验证
./gradlew :app:testDebugUnitTest
- 扩展工具顺序稳定 - 自定义 MCP / 扩展工具在工具提示词中按工具名排序输出,避免同一批工具因 Map/加载顺序变化导致提示词不稳定
- 工具调用次数提示去重 - 移除
ModelPromptController.buildToolPrompt中重复拼接的工具调用次数限制说明,改由工具提示构建逻辑统一处理;次数耗尽时仅提示“当前没有可用工具”,减少重复和冲突文案 - 系统提示模板顺序调整 -
{{TOOLS_CONTEXT}}从 Agent 协作规则前移到工作目录上下文之后,让工具清单更贴近当前工作区信息,降低提示词前段噪音
- Agent 进度回调栈溢出 - 修复 Agent / Agent Pipeline 工具进度回调在主线程同步派发时递归调用自身的问题;Release 混淆栈中的
hi.j()/t.run()死循环已定位为GenerationFlowController匿名 Host 回调未限定外部类方法,现改为明确调用外层控制器,避免StackOverflowError - 保活通知权限 - 补齐 Android 13+
POST_NOTIFICATIONS权限声明与运行时申请;用户开启前台服务通知或假音乐播放时会主动申请通知权限,权限返回后自动重新应用保活设置 - 前台保活通知实现 - 完善
KeepAliveService前台通知,补齐默认状态文案、通知点击回到 LineCode、service 分类、ticker 与可见性设置;无保活开关时会停止服务,避免空启动 - 假音乐播放保活 - 补上静音
AudioTrack循环播放实现,用户开启“假音乐播放”后后台任务期间会实际启动静音音频;任务结束或关闭开关时会停止并释放音频资源
- 新增
ToolSettingsRepositoryTest覆盖扩展工具按名称稳定排序输出 - 新增
GenerationFlowControllerTest覆盖 Agent 工具结果回调只派发一次,防止回归到递归栈溢出 - 已验证
testDebugUnitTest定向测试、compileDebugJavaWithJavac与assembleDebug
- MVP 控制器继续拆分 - 将聊天交互、生成流程、模型提示、会话持久化、上下文压缩、目录选择、扩展草稿、扩展管理、IPC Provider、文件树交互、项目工作区、模型交互、覆盖层动作、工具审批、工具消息与存储维护等职责拆到独立控制器,
MainCoordinator进一步收敛为协调入口,降低后续功能改动的冲突面 - 屏幕缓存与刷新机制 -
MainChatView新增屏幕缓存,切换设置/模型/扩展等页面时复用已构建视图;同时新增invalidateScreen刷新入口,支持在数据变化后精准重建当前页面 - 模型列表错误日志 - 查询模型列表与压缩模型列表失败时会写入错误日志中心,并对 API key 等敏感字段脱敏,方便定位第三方模型服务返回异常
- 停止生成时补齐 tool 消息 - 用户停止生成或工具执行被中断时,会为所有未完成的
tool_call追加错误态tool结果,并替换仍处于running、pending或空内容accepted状态的工具结果,避免后续请求因缺少 tool 消息而触发模型协议顺序错误 - 上下文窗口保持工具调用分组 -
ContextManager选择上下文窗口时会把 assistant 的tool_calls与对应tool结果作为一组保留,避免只保留 tool 结果或只保留 assistant tool_call 导致 OpenAI/Responses 等协议拒绝请求
- SSH 成功命令不再误报错误 - 修复 SSH 命令已成功结束但收尾读取阶段被中断时误标为失败、界面显示
错误:null的问题;命令通道关闭后会继续读取退出码和剩余输出,再恢复线程中断状态 - 工具执行错误文案更准确 -
ToolExecutor区分参数解析失败与工具执行失败;异常无 message 时显示异常类型或“未知错误”,不再把null拼进用户可见错误 - Shell 退出码展示修复 - IPC/终端提供者 shell 返回非 0 退出码且已有输出时,会同时保留命令输出和退出码,便于判断失败原因
- SSH 设置页错误显示修复 - SSH 连接测试失败时会显示可读异常描述,避免无 message 异常显示空白或
null - 主题页面文案修复 - 修复 Release 资源裁剪后主题页面显示
color_background、starter_high_contrast等带下划线 ID 的问题;主题模式、创作起点、颜色项和“当前编辑”标签改为直接引用多语言资源,中文环境下正常显示中文名称
- 新增
ToolMessageControllerTest覆盖停止生成时为所有未完成 tool call 补齐结果、保留已完成结果、替换 running 结果 - 新增
ToolExecutorTest覆盖无 message 异常不再渲染null - 扩展
ContextManagerTest覆盖 assistant tool_calls 与 tool 结果在上下文窗口中的成组保留
- 控制手机 (实验) - 新增手机控制能力,可在
设置 -> 高级功能 -> 控制手机中开启并配置权限;支持截图、坐标点击、滑动、长按、View 层级读取、按文本/资源 ID 点击 View,以及返回、主页、最近任务、通知栏、快捷设置、锁屏、退出当前应用等系统动作 - 截图与图片理解联动 - 手机截图改为保存到应用缓存目录并仅向 AI 返回图片路径,AI 可直接将路径传给现有图片理解工具;截图缓存会在应用启动时清理,避免长期占用存储
- 错误日志中心 - 新增
设置 -> 数据 -> 错误日志页面,遇到解析、HTTP、流式、SSE、IO、未捕获异常等错误时自动保存完整日志到应用私有目录;列表可查看日志,点击后可通过其他应用打开完整堆栈 - HTTP/解析诊断日志 - HTTP 与响应解析相关错误会记录完整请求、完整响应、流式已接收内容和异常堆栈,并自动脱敏
Authorization、x-api-key、JSON 密钥字段与大段图片/base64 内容 - 关于页 GitHub 入口 - 关于页面新增 GitHub 仓库入口,点击可跳转到
github.com/LangLang03/LineCodePro
- 手机控制工具卡片 - 控制手机工具调用不再按 MCP 通用 JSON 卡片展示,改为与文件读取、目录列表、搜索等工具一致的简洁展示;标题直接显示
截图、点击、滑动、长按、系统动作等具体操作名称 - 手机控制设置页 - 优化控制手机设置页面布局,权限申请、权限管理标题与开关行对齐;移除权限管理底部窄卡片背景,视觉上更接近普通设置列表
- 手机控制 i18n - 手机控制工具卡片、权限项、错误提示、执行结果等用户可见文案全部资源化,补齐英文与中文翻译,避免硬编码中文
- 图片理解模型提示调整 - 控制手机页面不再因未配置图片理解模型而禁用功能;未配置时由图片理解工具在实际调用时给出提示
- LLM 通信保活 - LLM 生成、流式响应和手动压缩期间临时启用前台保活服务与 WakeLock,降低应用进入后台后与 LLM 通信断开的概率;生成结束后会释放临时保活,不影响用户手动保活状态
- SSH 子 Agent 修复 - 修复
ssh模式下 Agent、Agent 编排、探索 Agent、Sub Coding 工具列表为空的问题,子 Agent 可正常使用远端 shell、搜索、任务清单、图片理解等工具 - SSH 只读策略调整 - SSH/终端提供者模式下不再通过工具过滤强制子 Agent 只读,而是通过提示词约束探索类 Agent 只执行只读命令;Agent 与 Agent Pipeline 在子 Agent 内继续黑名单递归调用,避免无限嵌套
- 终端提供者工具隔离 - SSH Shell 与终端提供者使用独立工具开关存储,关闭终端提供者的图片理解、Shell 等工具不会影响 SSH 模式,反之亦然
- 终端提供者命名优化 - 终端提供者里的 Shell 工具组改为
IPC Shell,描述改为通过终端提供者 IPC 执行,避免与 SSH Shell 混淆
- 无障碍状态检测 - 修复系统已开启无障碍但应用重进后工具调用误报“无障碍没打开”的问题;当授权存在但服务连接尚未恢复时,会短暂等待连接并给出更准确提示
- 截图兼容性崩溃 - 修复部分 Android 版本
AccessibilityService.ScreenshotResult无getBitmap()方法导致的反射崩溃问题 - 手机控制系统动作 - 新增独立系统动作工具与权限开关,补齐返回、主页、最近任务、通知栏、快捷设置、锁屏、电源菜单、退出当前应用等能力,避免 AI 无法退出 APP 或返回上一级
- 错误日志打开与清理 - 错误日志通过只读私有
ContentProvider授权单个日志文件给外部应用打开,右上角支持一键清空全部日志
- GPL 许可证打包 - 将 GPL 许可证作为 APK
META-INF/LICENSE随包分发,不放入strings.xml,不放入 Androidres/raw;Gradle packaging 保留该文件,避免被默认排除 - 日志脱敏 - 错误日志保存前自动脱敏密钥、鉴权头与超大图片内容,降低诊断日志泄露敏感信息的风险
- 新增
ToolSettingsRepositoryTest覆盖 SSH/终端提供者工具开关隔离、远端工具过滤与 IPC Shell 展示 - 新增
ErrorLogRedactorTest覆盖错误日志密钥、鉴权头和大段内容脱敏 - 已验证
compileDebugJavaWithJavac、lintDebug、assembleDebug,并检查 APK 内包含META-INF/LICENSE
- IPC 架构模块化 - 新增
ipc独立 Gradle 模块(ipc/),将原app内的 IPC 服务端/客户端抽象(IpcProviderManager、IpcProviderRegistry、IpcProviderScanner、IpcProviderConnectionState、IpcProviderStateListener、IpcProviderFactory、BaseIpcProvider、AbstractIpcProviderService、IpcServerExecutors、IpcServerPermission等)抽离到独立模块;terminal-provider模块新增TerminalIpcProvider/TerminalProviderServiceFactory接入新抽象;cn.lineai.ipc.terminal模块继续作为终端提供者实现,整体 IPC 拓扑从「app 内混合」改为「core 抽象 + provider 实现」分层 - Provider 管理器重构 -
IpcProviderManager改为支持工厂注册扩展(IpcProviderRegistry),新增全局观察者模式与连接状态机(IpcProviderConnectionState),供 UI 订阅 provider 连接生命周期 - MainCoordinator 内部类外提 - 8 个内联内部类(
AgentRunResult、PipelineAgent、AgentProgressMirror、AgentProgressSession、PipelineProgressSession、PipelineAgentState、ToolExecutionBatch、PendingToolExecution)抽取为cn.lineai.mvp.agent包下的独立顶层类;MainCoordinator由 561 行 → 180 行;统一以 getter 替换直接字段访问,简化Collections.singletonList调用 - AgentExecutionController 抽取 - 将
MainCoordinator内联 Agent 与 Pipeline Agent 执行相关代码(590 行)抽离到独立AgentExecutionController;MainCoordinator由 639 行 → 49 行,职责简化为协调调度 - 实验性功能与插件页清理 - 移除
ExperimentalSettingsScreenView、PluginPageScreenView页面与ScreenFactories中的注册;清理SettingsScreenView、ScreenNavigationController、MainChatView、SimpleScreenContent中的实验性入口与冗余资源;values/strings.xml与values-zh/strings.xml同步删除对应文案 - 教程页重构 - 新增
app/src/main/assets/tutorials/simple.md(78 行)与pro.md(217 行)两套内置教程源;TutorialScreenView支持从 assets 读取 Markdown 渲染,新增简单模式与专业模式分类 - Markdown 渲染 -
MarkdownView扩展 36 行,支持教程页与错误状态文本渲染 - AssistantMessageView 错误态 - 新增错误状态纯文本渲染支持
- 附件选择器 -
AttachmentPickerCoordinator调整 73 行以适配新 IPC 抽象
- README 社交预览 -
README.md与README_CN.md顶部新增动态社交预览横幅 - ipc 模块文档 - 新增
ipc/README.md(741 行)与ipc/README_CN.md(739 行),介绍 IPC 抽象、Provider 注册、连接状态机、权限模型与扩展方式
- IPC 终端提供者 - 新增
cn.lineai.ipc.terminal模块,通过 AIDL 跨进程调用终端提供者服务执行 SHELL/SFTP/文件读写操作;支持executeShell、readFile/writeFile、readFileChunk/writeFileChunk(大文件分块,1MB 上限)、listDirDetailed、statFile、getFileSize等接口 - AIDL 混淆保护 -
proguard-rules.pro新增 IPC 接口 keep 规则,保护 AIDL 生成的Stub/Proxy/asInterface入口类名,避免 release 包跨进程 Binder 调用失败
- Repository 接口抽象 - 为
ConversationRepository/ProjectRepository/ModelRepository/DiffRepository/ExtensionRepository/IpcProviderRepository/LearningContextRepository/ToolSettingsRepository/FileTreeRepository/IpcFileTreeRepository/SshFileTreeRepository抽取*Store接口;MainDependencies字段类型改为接口 - BaseRepository 公共基类 - 抽取
database字段与value/intValue/longValue/safeCursor 辅助方法,消除各 Repository 重复代码 - ExtensionRepository 拆分 - 1232 行巨型门面拆为
AgentExtensionRepository、McpExtensionRepository、SkillRepository三个子 Repository;ExtensionRepository降为 103 行纯门面 - LearningContextRepository 拆分 - 793 行拆为
MemoryRanker(BM25 排序)、TextTokenizer(CJK 双字分词)、ConversationIndexer(对话索引)三个独立类 - MainCoordinator 拆分 - 5046 行 → 4981 行,提取
AttachmentPickerCoordinator接管附件选择器的 8 个状态字段与 7 个方法 - MainChatView 拆分 - 1589 行 → 789 行(-50%),提取
ScreenFactory注册表(582 行buildScreen→ 7 行委托)、DialogManager、PermissionUiHelper、MainChatViewLayoutBuilder、SimpleScreenContent、FileActionRow、BackNavigation、DialogDimensions、SafPickerDelegate共 9 个独立类 - 巨型 Controller 拆分 -
SettingsController拆为 7 个细粒度接口(AiBehaviorSettingsController / InputSettingsController / OutputSettingsController / ThemeSettingsController / McpSettingsController / ArchiveController / StorageController);MainContract.View拆为 5 个细粒度接口(ChatRenderView / OverlayView / PickerView / ScreenView / PermissionView) - 过长方法拆分 -
CodexResponsesProtocol.stream()(122→28)、AnthropicMessagesProtocol.stream()(87→30)、ToolCallWriteView.bind()(130→20)、MarkdownRenderer.renderBlock()(70→9) - 重复代码消除 -
RemoteFileTreeController公共基类;BaseTool.ok/error上移;FileIo.readUtf8提取;ToolArgs.requireNonEmpty提取;BaseToolCallView抽象基类;thinkingBudget上移到AbstractHttpModelProtocol - OCP 改造 -
ModelProtocolFactory、Migrations、ArchiveSecretRedactor改为注册表实现,新增工具通过BuiltInToolProvider注册到BuiltInToolProviders.defaults()即可 - SshService 拆分 - 提取
SshConnectionPool(连接复用缓存)与TermuxHelper(Termux 集成独立类);termux_setup.sh移至 assets 资源 - ContextCompactionService 依赖注入 - 构造函数注入
ModelClient/OpenAiResponsesCompactionProtocol/CodexResponsesProtocol/PromptTemplateRepository;MemoryExtractionService从data.repository包移至context包修复反向依赖 - 字符串外部化 - 所有硬编码中文字符串替换为
strings.xml资源引用,英文 / 中文分别放在values/和values-zh/ - 兼容性代码清理 - 移除
getSelectedProjectLegacy、SshService.TERMUX_*委托字段、SshService.TermuxSetupResult委托类、MainActivity.Legacy branch注释等兼容代码
- HttpServerTool 健壮性 - 请求头读取改为循环至结束标记(8192 字节上限);
new Thread替换为 10 线程固定线程池;Socket.setSoTimeout(30s);异常记录Log.w不再静默 - AIDL 大文件 -
ITerminalProviderService新增readFileChunk/writeFileChunk/getFileSize三个分块方法,避免 1MB+ 事务缓冲区溢出 - SshService TOFU -
TrustOnFirstUseUserInfo.promptYesNo添加警告日志,降低中间人攻击风险 - 数据库迁移 -
LineCodeSchema集中 SQL 常量;AddToolCallObservabilityColumns.apply通过PRAGMA table_info检查避免重复列;onCreate与onUpgrade职责厘清 - IPC 权限 - 新增
IpcProviderScanner/BaseIpcProvider校验 target service signature fingerprint
- UrlPolicy SSRF 加固 - 增加内网 IP 段黑名单(192.168/10/172.16-31)、端口白名单(80/443/8080/8443)、URL 用户信息(user:pass@host)校验
- KeepAliveService - 移除静音音频 hack;WakeLock 与任务生命周期绑定
- requestLegacyExternalStorage - 移除冗余声明
- AIDL 调用方权限 - 在
ITerminalProviderService.aidl注释中声明调用方所需权限
- 新增
UrlPolicyTest覆盖 SSRF 新增场景 - 新增
LineCodeSchemaTest、AddToolCallObservabilityColumnsTest、MigrationsTest覆盖迁移框架 - 新增多个 Repository / Controller / Service 单测
- 数据库迁移框架 - 新增版本化迁移系统:抽象类
DatabaseMigration、Migrations.all()迁移注册表、schema_migrations迁移记录表;onUpgrade路径由"DROP 全部表 + onCreate 重建"改为"按版本顺序应用迁移",升级不再破坏用户数据 - tool_call 可观测字段 -
tool_calls表新增duration_ms INTEGER NOT NULL DEFAULT 0与error_message TEXT两列,支持记录工具耗时与失败原因 - TODO 任务清单 - 新增
todo_update工具与卡片视图,模型在每轮开始可把计划拆分为三态任务项(未开始 / 进行中 / 已完成),工具卡片会跟随消息流滚动,并在每次列表变化时追加新卡片 - TODO 状态注入 - 当前任务清单每轮自动注入到系统提示词的
{{TODO_STATE}}占位符,模型能感知待办进度 - 工具与执行页开关 - 任务清单、Agent、Agent Pipeline 在本地模式与 SSH 模式下均显示开关;Agent 与 Agent Pipeline 在 SSH 模式下可用,子 Agent 通过
shell_execute在 SSH 环境内完成文件操作
- 数据库迁移崩溃 - 修复
LineCodeDatabase.applyMigrations在onUpgrade路径上未先创建schema_migrations表就尝试INSERT导致的SQLiteException: no such table: schema_migrations崩溃;v1→v2 升级路径现在安全 - .linecode 归档导入校验 -
LineCodeDatabaseArchive拒绝导入由更高版本生成的快照,避免数据丢失;旧版本快照导入时打印警告日志 - 归档 schemaVersion 硬编码 -
LineCodeArchiveCodec写出的schemaVersion从硬编码2改为读取LineCodeSchema.VERSION,未来升级不再失同步
- 新增
LineCodeSchemaTest、AddToolCallObservabilityColumnsTest、MigrationsTest单测覆盖迁移框架与 schema 变更
- 添加自定义 MCP - 修复
SettingsSectionView.addRow中 view parent 状态泄漏导致的IllegalStateException,连续添加 3 个及以上自定义请求头不再闪退;McpExtensionEditScreenView.save()在未查询 tools 或 URL 变更时拒绝保存,避免保存无效 MCP
- 自定义 Agent UI - 修复用户自定义 Agent 扩展(agentx_*)使用 MCP 通用组件渲染的问题,现在正确使用内置 Agent 专用组件,支持类型标签、嵌套工具调用展示、thinking 块、流式进度等完整 Agent UI 能力,并修复Agent无法使用部分TOOL和MCP的问题
- 修复 GitHub Actions Release 变量传递问题,正确显示版本名称
- 模型选择器 - 模型快速切换按钮宽度改为自适应,根据模型名称长度自动调整
- 通知权限 - 修复 Android 13+ 保活服务通知权限检查问题
- CI/CD - 修复 GitHub Actions 签名配置路径问题
- 保活服务 - 新增后台保活功能,支持长时间运行任务
- 存储管理 - 添加存储统计与管理页面
- 代理流水线 - 实现 Agent Pipeline 多步骤执行能力
- 模型快速切换 - 聊天界面新增模型下拉框,支持快速切换模型
- 模型身份提示 - 支持模型身份信息注入到系统提示词
- 自动发布 - 新增 GitHub Actions Release APK 自动构建与发布流程
- 版本触发 - 版本号变更时自动触发构建,发布到 GitHub Releases
- 更新日志 - 新增
update.md文件,自动读取版本更新内容
- 重构模型管理 API 与工具检查逻辑
- 更新聊天消息处理流程
- 图片生成工具 - 新增 ImageGenerationTool,支持 AI 图片生成
- 图片理解工具 - 新增 ImageUnderstandingTool,支持图片内容分析
- 数据导入导出 - 支持
.linecode格式的完整数据备份与恢复 - 会话级工具确认 - 实现会话级自动确认工具执行,减少重复确认
- 输入设置 - 新增输入设置页面,支持回车键行为自定义
- 完成安卓合规审计相关的安全加固与优化
- URL 策略强制 HTTPS,限制明文流量
- WebView 安全配置强化
- 新增多语言文档
- 添加许可证文件
- 提示词模板管理 - 新增提示词模板管理功能
- 消息附件支持 - 实现消息附件支持与消息操作功能
- 输入设置页面 - 新增输入设置页面和回车键行为控制
- 多项功能优化与 bug 修复
- 聊天模式 - 添加聊天模式功能
- 扩展系统 - 新增扩展系统与技能管理能力
- SSH Shell 工具 - 新增 SSH Shell 工具与上下文压缩功能
- 项目管理 - 完善项目管理与 UI 体验
- AI 聊天 - 基于 LLM 的智能对话系统
- 工具系统 - 文件读写、Shell 执行、Web 搜索等内置工具
- 工作区管理 - SAF 文件树选择与项目管理
- MVP 架构 - 单 Activity MVP 架构设计
- 多模型协议 - 支持 OpenAI Compatible、Anthropic、Codex Responses 等协议