diff --git a/README.md b/README.md index d53cf04b..15e4533c 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [![License: GPL-3.0-or-later](https://img.shields.io/badge/License-GPL--3.0--or--later-blue.svg)](LICENSE) [![Android 8.0+](https://img.shields.io/badge/Android-8.0%2B%20(API%2026)-3DDC84.svg)](app/build.gradle.kts) -[![Latest: 1.2.2](https://img.shields.io/badge/version-1.2.2-success.svg)](app/build.gradle.kts) +[![Latest: 1.2.8-max](https://img.shields.io/badge/version-1.2.8--max-success.svg)](app/build.gradle.kts) [![Java only](https://img.shields.io/badge/code-Java%2011-orange.svg)](#project-layout) --- @@ -19,17 +19,18 @@ 1. [What is LineCode Pro?](#what-is-linecode-pro) 2. [What it can do](#what-it-can-do) 3. [Highlights](#highlights) -4. [Project layout](#project-layout) -5. [Install](#install) -6. [Getting started](#getting-started) -7. [Execution modes](#execution-modes) -8. [Model providers](#model-providers) -9. [Tool system](#tool-system) -10. [Extending LineCode](#extending-linecode) -11. [Building from source](#building-from-source) -12. [Privacy & security](#privacy--security) -13. [Contributing](#contributing) -14. [License](#license) +4. [What's new in v1.2.8-max](#whats-new-in-v128-max) +5. [Project layout](#project-layout) +6. [Install](#install) +7. [Getting started](#getting-started) +8. [Execution modes](#execution-modes) +9. [Model providers](#model-providers) +10. [Tool system](#tool-system) +11. [Extending LineCode](#extending-linecode) +12. [Building from source](#building-from-source) +13. [Privacy & security](#privacy--security) +14. [Contributing](#contributing) +15. [License](#license) --- @@ -39,7 +40,7 @@ LineCode is not a thin chat client. It is a full coding workspace: the system prompt, the tool registry, the context manager, the diff store, the file tree, the project picker, the SSH / IPC plumbing, the import/export archive, the extensions framework, and the security policy all live in the app. Nothing leaves your phone unless you wire it up to a remote model. -The application id is `cn.lineai` and the project is a multi-module Gradle project with 12 modules: `:build-logic` (composite build), `:core-model`, `:core-api`, `:core-security`, `:ui-theme`, `:markdown`, `:data`, `:feature-tool`, `:feature-model`, `:feature-ssh`, `:feature-share`, `:app`, plus the reusable `:ipc` library and the sample `:terminal-provider` app. +The application id is `cn.lineai` and the project is a multi-module Gradle project with 14 included modules: `:core-model`, `:core-api`, `:core-security`, `:ui-theme`, `:markdown`, `:data`, `:feature-tool`, `:feature-model`, `:feature-ssh`, `:feature-share`, `:tool-ui`, `:app`, the reusable `:ipc` library, and the sample `:terminal-provider` app. `:build-logic` is included as a composite build. --- @@ -49,6 +50,7 @@ The application id is `cn.lineai` and the project is a multi-module Gradle proje - Streaming chat with **multiple model protocols** in the same UI: OpenAI-compatible HTTP APIs, Anthropic Messages, OpenAI Codex Responses, and a local GGUF runtime. - Reasoning blocks (``) are extracted and rendered separately from the final answer. +- Each assistant turn is rendered as an expandable processing timeline: reasoning, grouped tool calls, retries, errors, and Agent progress stay in order while the final answer remains separate. Completed processing duration is persisted with the message. - Tool-call text inside a stream is parsed and dispatched by `ToolCallTextParser`; everything the model asks to do is shown to you before it runs. - System prompts are assembled from `feature-model/src/main/assets/prompts/*.txt` — tone variants (chat / coding), context-compaction, work-directory, learning-context, and model-identity templates. You can override the tone, the work directory, the identity block, and the prompt template from settings. - Long conversations are summarised in the background by `ContextCompactionService` with **dynamic compaction** (50% soft trigger + 80% hard trigger) using the active model itself; durable knowledge saved via the `memory_update` tool or the memory screen is reinjected next session by `LearningContextRepository`. @@ -64,10 +66,10 @@ The model has access to a registry of tools (`ToolRegistry`) with session-scoped | Shell | `shell_execute` (Termux or via IPC) | | Web | `web_search`, `web_fetch` | | Media | `image_understanding`, `image_generation` | -| Sub-agents | `agent`, `agent_pipeline` (delegate work to another LLM loop) | +| Sub-agents | `agent`, `agent_pipeline`, `agent_output` (delegate work to another LLM loop) | | Productivity| `todo_update` | -Every file-touching tool routes paths through `FileToolPathPolicy` so the model can only act inside the workspace you opened. Shell calls go through Termux or an IPC provider — never the app process itself. +Every file-touching tool routes paths through `FileToolPathPolicy` so the model can only act inside the workspace you opened. Shell calls go through Termux or an IPC provider — never the app process itself. Confirmation mode supports one-time approval and persistent, exact-match command permissions scoped by execution mode, tool, command, and working directory. ### Context protection @@ -112,6 +114,17 @@ Every file-touching tool routes paths through `FileToolPathPolicy` so the model - **Private by default.** URL allow-list, strict `network_security_config.xml`, secrets redacted from exports, in-app browser keeps JavaScript off. - **Java-only, on purpose.** No Kotlin runtime, no XML layouts — the app is built entirely in Java 11 for transparency and reviewability. +## What's new in v1.2.8-max + +The current release focuses on a denser native Android UI and a clearer model-workflow surface: + +- **Native UI refresh.** Chat, settings, drawers, sheets, tool cards, themes, Markdown, wide-screen layouts, large text, and narrow-screen actions were rebuilt around shared adaptive View components. +- **Processing timeline.** Reasoning, tool groups, Agent cards, retries, errors, work status, and final answers are presented in the order they happen, with compact expandable summaries and persisted processing duration. +- **Safer execution approvals.** Automatic, confirmation, and read-only modes are aligned across the main flow and Agents. Permanent approvals match the full execution scope, tool, command, and working directory. +- **Skill Hub.** Browse and search community Skills, inspect files, versions, comments, evaluations, previews, and security hints, then sign in, install, publish, and manage community Skills from the app. +- **Prompt and context stability.** Stable system prefixes, deterministic tool/extension ordering, canonical JSON serialization, attachment-local context, and corrected post-compaction token baselines improve cache reuse and prevent repeated compaction. +- **Release verification.** Robolectric 4.16 native View tests cover layouts, timelines, permissions, prompts, Skill Hub flows, and diff rendering; the v1.2.8-max release notes record 528 passing unit tests plus successful Debug/DebugUserCert builds and lint. + --- ## Project layout @@ -152,6 +165,7 @@ LineCode/ │ └── ai/message/ # SystemModelMessage, UserModelMessage, etc. ├── feature-ssh/ # :feature-ssh — SshService, SshConnectionPool, TermuxHelper ├── feature-share/ # :feature-share — export/share/PDF +├── tool-ui/ # :tool-ui — reusable tool-call cards and view registry ├── app/ # :app — MainActivity, MainCoordinator, controllers, UI components │ ├── build.gradle.kts │ ├── lint.xml @@ -276,10 +290,10 @@ Built-in tools live in `feature-tool/src/main/java/cn/lineai/tool/builtin/`: FileReadTool FileWriteTool FileEditTool FileDeleteTool GlobTool ListDirectoryTool ShellExecuteTool ImageUnderstandingTool ImageGenerationTool WebSearchTool WebFetchTool -AgentTool AgentPipelineTool TodoUpdateTool +AgentTool AgentPipelineTool AgentOutputTool TodoUpdateTool ``` -Execution is driven by `ToolExecutionCoordinator` + `ToolExecutor`. Every call goes through `PermissionModeController` + `ToolReviewListener`; the user can confirm per-call or auto-confirm for the session. The list of auto-confirmed tools is tracked on the coordinator (`MainCoordinator.sessionAutoConfirmedTools`). +Execution is driven by `ToolExecutionCoordinator` + `ToolExecutor`. Every call goes through `PermissionModeController` + `ToolReviewListener`; automatic, confirmation, and read-only modes are supported. Confirmation mode offers one-time approval or persistent exact-match permissions scoped by execution mode, tool, command, and working directory. Tool results are truncated at 50KB by `ToolResult.truncateContent()` before entering the context. File reads use KB-based parameters with a 50KB range limit; files over 1MB are rejected. Shell outputs exceeding 50KB are middle-truncated. @@ -297,6 +311,8 @@ Three extension points are first-class: All three are persisted via `ExtensionRepository` and hot-reloaded by `ToolRegistry.reloadExtensions()`. +The built-in **Skill Hub** in the Extensions area lets you discover, review, install, and manage community Skills. URI, GitHub, and Skill Hub installs share the same temporary-source cleanup and file-management path. + --- ## Building from source @@ -320,7 +336,7 @@ All Gradle commands go through the wrapper. The settings file forces `FAIL_ON_PR ./gradlew :app:assembleDebugUserCert # → app/build/outputs/apk/debugUserCert/export/LineCode-user-cert-debug.apk -# Run the unit test suite (JUnit 4 only, no Robolectric) +# Run the unit test suite (JUnit 4 + Robolectric 4.16 where Android resources are needed) ./gradlew :app:testDebugUnitTest # Run a single test class @@ -400,7 +416,7 @@ Bug reports, ideas and patches are welcome. A few notes if you plan to send code * **Views in Java, not XML.** `lint.xml` silences `ViewConstructor` and `IconDuplicates` deliberately. * **Choose the lowest-level module.** When adding code, pick the lowest-level module that fits: DTOs → `:core-model`; interfaces → `:core-api`; UI infrastructure → `:ui-theme`; a new tool → `:feature-tool`; a new protocol → `:feature-model`. Do not reach back into `:app` from a library module. * **Extend the controllers.** When adding chat or tool behaviour, extend the matching controller in `cn.lineai.mvp.*` and thread state through `ChatUiStateAssembler` → `ChatUiState` → `MainContract.View.render(...)`. Do not reach into views from new code. -* **Tests mirror the package layout.** `app/src/test/java/cn/lineai/...` mirrors production. JUnit 4 + `org.json` only (no Robolectric, no Mockito). When testing repository or controller logic, prefer the in-memory fakes that already exist in sibling tests. Feature modules have their own tests under `feature-*/src/test/java`. +* **Tests mirror the package layout.** `app/src/test/java/cn/lineai/...` mirrors production. Tests use JUnit 4, `org.json`, and Robolectric 4.16 for Android resource/View behavior (no Mockito). When testing repository or controller logic, prefer the in-memory fakes that already exist in sibling tests. Feature modules have their own tests under `feature-*/src/test/java`. * **Run the gates before sending a PR:** ```bash @@ -429,4 +445,4 @@ GNU General Public License for more details. Full text in [`LICENSE`](LICENSE). Online copy at . -Third-party libraries shipped with the APK keep their own licenses: commonmark (BSD-2), JSch (BSD-style), org.json (JSON License). \ No newline at end of file +Third-party libraries shipped with the APK keep their own licenses: commonmark (BSD-2), JSch (BSD-style), org.json (JSON License). diff --git a/README_CN.md b/README_CN.md index 8a115e9c..269df289 100644 --- a/README_CN.md +++ b/README_CN.md @@ -9,7 +9,7 @@ [![许可证: GPL-3.0-or-later](https://img.shields.io/badge/license-GPL--3.0--or--later-blue.svg)](LICENSE) [![Android 8.0+](https://img.shields.io/badge/Android-8.0%2B%20(API%2026)-3DDC84.svg)](app/build.gradle.kts) -[![当前版本: 1.2.2](https://img.shields.io/badge/version-1.2.2-success.svg)](app/build.gradle.kts) +[![当前版本: 1.2.8-max](https://img.shields.io/badge/version-1.2.8--max-success.svg)](app/build.gradle.kts) [![Java 11 only](https://img.shields.io/badge/code-Java%2011-orange.svg)](#项目结构) --- @@ -19,17 +19,18 @@ 1. [LineCode Pro 是什么?](#linecode-pro-是什么) 2. [它能做什么](#它能做什么) 3. [功能亮点](#功能亮点) -4. [项目结构](#项目结构) -5. [安装](#安装) -6. [上手指南](#上手指南) -7. [执行模式](#执行模式) -8. [支持的模型协议](#支持的模型协议) -9. [工具系统](#工具系统) -10. [扩展 LineCode](#扩展-linecode) -11. [从源码构建](#从源码构建) -12. [隐私与安全](#隐私与安全) -13. [参与贡献](#参与贡献) -14. [许可证](#许可证) +4. [v1.2.8-max 更新内容](#v128-max-更新内容) +5. [项目结构](#项目结构) +6. [安装](#安装) +7. [上手指南](#上手指南) +8. [执行模式](#执行模式) +9. [支持的模型协议](#支持的模型协议) +10. [工具系统](#工具系统) +11. [扩展 LineCode](#扩展-linecode) +12. [从源码构建](#从源码构建) +13. [隐私与安全](#隐私与安全) +14. [参与贡献](#参与贡献) +15. [许可证](#许可证) --- @@ -39,7 +40,7 @@ LineCode 不是一个轻量聊天客户端,它是一个**完整的编程工作台**:系统提示、工具注册表、上下文管理、Diff 存档、文件树、项目选择器、SSH / IPC 管道、导入导出归档、扩展框架、安全策略……全部跑在 App 内部。除非你自己接到远程模型,否则项目文件不会离开你的手机。 -应用包名是 `cn.lineai`,仓库采用 12 模块 Gradle 结构:`:build-logic`(composite build)、`:core-model`、`:core-api`、`:core-security`、`:ui-theme`、`:markdown`、`:data`、`:feature-tool`、`:feature-model`、`:feature-ssh`、`:feature-share`、`:app`,外加可复用库 `:ipc` 与示例 Provider `:terminal-provider`。 +应用包名是 `cn.lineai`,仓库采用 14 个 Gradle 模块:`:core-model`、`:core-api`、`:core-security`、`:ui-theme`、`:markdown`、`:data`、`:feature-tool`、`:feature-model`、`:feature-ssh`、`:feature-share`、`:tool-ui`、`:app`、可复用库 `:ipc` 与示例 Provider `:terminal-provider`;`:build-logic` 作为 composite build 引入。 --- @@ -49,6 +50,7 @@ LineCode 不是一个轻量聊天客户端,它是一个**完整的编程工作 - 同一个聊天界面下支持**多种模型协议**:OpenAI 兼容 HTTP API、Anthropic Messages、OpenAI Codex Responses、本地 GGUF 推理。 - 推理块(``)会被 `ThinkTagParser` 单独抽出来,和最终回答分块渲染。 +- 每轮助手消息都按发生顺序渲染为可展开的处理时间线:思考、工具分组、重试、错误和 Agent 进度集中展示,最终答复保持独立;处理耗时会随消息持久化。 - 流中的工具调用文本由 `ToolCallTextParser` 解析并派发;模型请求做的每件事,在真正执行前都会先展示给你看。 - 系统提示由 `feature-model/src/main/assets/prompts/*.txt` 中的模板拼装:语气(聊天 / 编程)变体、上下文压缩、工作目录、学习上下文、模型身份。你可以在设置里覆盖语气、工作目录、身份块、提示模板。 - 长对话由 `ContextCompactionService` 后台用**当前模型本身**做**动态压缩**(50% 软触发 + 80% 硬触发);通过 `memory_update` 工具或记忆管理界面保存的长期知识,由 `LearningContextRepository` 在下一次会话中喂回上下文。 @@ -56,7 +58,7 @@ LineCode 不是一个轻量聊天客户端,它是一个**完整的编程工作 ### 工具执行 -模型可以调用 `ToolRegistry` 里的全部工具,并支持会话级自动确认: +模型可以调用 `ToolRegistry` 里的全部工具,并支持自动、确认和只读执行模式: | 分类 | 内置工具 | | ---- | -------- | @@ -64,10 +66,10 @@ LineCode 不是一个轻量聊天客户端,它是一个**完整的编程工作 | Shell | `shell_execute`(经 Termux 或 IPC Provider) | | 网络 | `web_search`、`web_fetch` | | 媒体 | `image_understanding`、`image_generation` | -| 子任务 | `agent`、`agent_pipeline`(分派给另一个 LLM 循环) | +| 子任务 | `agent`、`agent_pipeline`、`agent_output`(分派给另一个 LLM 循环) | | 效率 | `todo_update` | -每个会触碰文件的工具都走 `FileToolPathPolicy` 路径校验,模型只能动你授权的目录里的内容。Shell 调用走 Termux 或 IPC Provider —— **永远不在 App 自身进程里跑命令**。 +每个会触碰文件的工具都走 `FileToolPathPolicy` 路径校验,模型只能动你授权的目录里的内容。Shell 调用走 Termux 或 IPC Provider —— **永远不在 App 自身进程里跑命令**。确认模式支持单次允许和永久精确匹配授权,范围包含执行模式、工具、完整命令和工作目录。 ### 上下文保护 @@ -102,7 +104,7 @@ LineCode 不是一个轻量聊天客户端,它是一个**完整的编程工作 ## 功能亮点 - **一个聊天,多家后端。** OpenAI 兼容、Anthropic Messages、Codex Responses、本地 GGUF 在同一 UI 内任意切换。 -- **真正能干活的工具循环。** 模型能读、改、glob、新建、删除文件,能跑 Shell,能抓取和搜索网页,能看图,能生图,能递归调子任务 —— 全部由你逐条审批或会话级自动确认。 +- **真正能干活的工具循环。** 模型能读、改、glob、新建、删除文件,能跑 Shell,能抓取和搜索网页,能看图,能生图,能递归调子任务 —— 全部受自动、确认或只读模式控制。 - **可在任意目录工作。** 本地(SAF + 可选 `MANAGE_EXTERNAL_STORAGE`)、远程(jsch SSH)、或第三方 IPC Provider。 - **支持自定义扩展。** 自定义 Agent(`agentx_*`)和 MCP-HTTP 工具(`mcpx_*`)即配即用。 - **可插拔 IPC Provider。** 把 Shell 和文件操作放到独立进程里以做安全隔离。可以把 Provider 当成普通 Android App 上架,详见 [`ipc/README.md`](ipc/README.md)。 @@ -112,6 +114,17 @@ LineCode 不是一个轻量聊天客户端,它是一个**完整的编程工作 - **默认隐私优先。** URL 白名单、严格 `network_security_config.xml`、导出文件去敏、内置浏览器默认关闭 JavaScript。 - **纯 Java 写在骨子里。** 无 Kotlin 运行时、无 XML 布局 —— App 全部由 Java 11 写成,便于审计。 +## v1.2.8-max 更新内容 + +当前版本重点更新了更紧凑的 Android 原生界面和更清晰的模型工作流: + +- **原生 UI 重写。** 聊天、设置、抽屉、底部弹窗、工具卡片、主题、Markdown、宽屏布局、大字体和窄屏操作统一使用共享的自适应 View 组件。 +- **处理时间线。** 思考、工具组、Agent 卡片、重试、错误、工作状态和最终答复按实际发生顺序展示,过程默认紧凑折叠,处理耗时会持久化。 +- **更安全的执行授权。** 自动、确认、只读模式在主流程与 Agent 内统一生效;永久授权精确匹配完整的执行范围、工具、命令和工作目录。 +- **Skill Hub。** 可在应用内搜索和浏览社区 Skills,查看文件、版本、评论、评测、预览和安全提示,并完成登录、安装、发布与管理。 +- **提示词与上下文稳定性。** 固定系统前缀、稳定的工具 / 扩展排序、规范化 JSON、附件归属原消息,以及压缩后的用量基线修复,改善缓存复用并避免重复压缩。 +- **发版验证。** Robolectric 4.16 原生 View 测试覆盖布局、时间线、权限、提示词、Skill Hub 流程和 Diff;v1.2.8-max 更新日志记录相关模块单元测试 **528 项通过**,主应用 Debug / DebugUserCert 构建和 Lint 也已通过。 + --- ## 项目结构 @@ -152,6 +165,7 @@ LineCode/ │ └── ai/message/ # SystemModelMessage、UserModelMessage 等 ├── feature-ssh/ # :feature-ssh — SshService、SshConnectionPool、TermuxHelper ├── feature-share/ # :feature-share — 导出 / 分享 / PDF +├── tool-ui/ # :tool-ui — 可复用工具调用卡片和 View 注册表 ├── app/ # :app — MainActivity、MainCoordinator、控制器、UI 组件 │ ├── build.gradle.kts │ ├── lint.xml @@ -274,10 +288,10 @@ LineCode 在 **设置 → MCP execution mode** 里提供三种 Shell / 文件工 FileReadTool FileWriteTool FileEditTool FileDeleteTool GlobTool ListDirectoryTool ShellExecuteTool ImageUnderstandingTool ImageGenerationTool WebSearchTool WebFetchTool -AgentTool AgentPipelineTool TodoUpdateTool +AgentTool AgentPipelineTool AgentOutputTool TodoUpdateTool ``` -执行由 `ToolExecutionCoordinator` + `ToolExecutor` 驱动;每次调用都要过 `PermissionModeController` + `ToolReviewListener`,用户可逐条确认或会话级自动确认。自动确认列表由 `MainCoordinator.sessionAutoConfirmedTools` 跟踪。 +执行由 `ToolExecutionCoordinator` + `ToolExecutor` 驱动;每次调用都要过 `PermissionModeController` + `ToolReviewListener`,支持自动、确认和只读模式。确认模式提供单次允许或永久精确匹配授权,授权范围包含执行模式、工具、命令和工作目录。 工具结果由 `ToolResult.truncateContent()` 在 50KB 处截断(首尾各 25KB)后进入上下文。文件读取使用 KB 参数,50KB 范围上限;超过 1MB 的文件直接拒绝。Shell 输出超过 50KB 同样中间截断。 @@ -295,6 +309,8 @@ AgentTool AgentPipelineTool TodoUpdateTool 以上三类都通过 `ExtensionRepository` 持久化,由 `ToolRegistry.reloadExtensions()` 热加载。 +扩展页面内置 **Skill Hub**,可以发现、审查、安装和管理社区 Skills。URI、GitHub 与 Skill Hub 安装共用临时来源清理和文件管理流程。 + --- ## 从源码构建 @@ -318,7 +334,7 @@ AgentTool AgentPipelineTool TodoUpdateTool ./gradlew :app:assembleDebugUserCert # → app/build/outputs/apk/debugUserCert/export/LineCode-user-cert-debug.apk -# 单元测试 +# 单元测试(需要 Android 资源 / View 行为时使用 JUnit 4 + Robolectric 4.16) ./gradlew :app:testDebugUnitTest # 单个测试类 @@ -398,7 +414,7 @@ Release 流水线刻意加强: * **视图用 Java 写,不用 XML。** `lint.xml` 故意屏蔽 `ViewConstructor` 与 `IconDuplicates`。 * **选择最低层模块。** 加新代码时挑能容纳它的最低层模块:DTO → `:core-model`;接口 → `:core-api`;UI 基础设施 → `:ui-theme`;新工具 → `:feature-tool`;新协议 → `:feature-model`。库模块不要回头引用 `:app`。 * **通过控制器扩展。** 新增聊天或工具行为时,扩展 `cn.lineai.mvp.*` 下对应的控制器,状态走 `ChatUiStateAssembler` → `ChatUiState` → `MainContract.View.render(...)`。不要绕过控制器去直接动 View。 -* **测试镜像包路径。** `app/src/test/java/cn/lineai/...` 与生产代码同包名。仅用 JUnit 4 + `org.json`(无 Robolectric、无 Mockito)。仓库或控制器单测优先用 sibling test 里已有的内存 fake。Feature 模块有各自独立的 `feature-*/src/test/java`。 +* **测试镜像包路径。** `app/src/test/java/cn/lineai/...` 与生产代码同包名。测试使用 JUnit 4、`org.json`,并在需要 Android 资源 / View 行为时使用 Robolectric 4.16(无 Mockito)。仓库或控制器单测优先用 sibling test 里已有的内存 fake。Feature 模块有各自独立的 `feature-*/src/test/java`。 * **发 PR 前跑门禁:** ```bash @@ -427,4 +443,4 @@ GNU General Public License for more details. 许可证全文见 [`LICENSE`](LICENSE),在线副本:。 -随 APK 一起分发的第三方库各自遵循自己的许可证:commonmark(BSD-2)、JSch(BSD 风格)、org.json(JSON License)。 \ No newline at end of file +随 APK 一起分发的第三方库各自遵循自己的许可证:commonmark(BSD-2)、JSch(BSD 风格)、org.json(JSON License)。