Repository navigation
feat: 1.3.3 — 工作区挂载到文件系统、极简模式与记忆删除修复 - #36
Conversation
审阅者指南本 PR 将内部工作区升级为安全的 SAF DocumentsProvider 并接入系统目录选择器,同时新增极简提示词模式、统一上下文估算与自动压缩口径、修正 DeepSeek 推理请求协议、修复旧版 FTS4 索引导致的记忆删除失败,并发布 Android v1.3.3。 在 Files 中挂载工作区的时序图sequenceDiagram
participant User
participant Extensions
participant Channel
participant Picker
participant Provider
participant Workspace
User->>Extensions: MountWorkspace()
Extensions->>Channel: mountWorkspace
Channel->>Picker: ACTION_OPEN_DOCUMENT_TREE
Picker->>Provider: rootDocumentUri
Provider->>Workspace: queryRoots()
Provider-->>Picker: .linecode root
User->>Picker: Grant directory access
Picker->>Provider: queryChildDocuments()
Provider->>Workspace: Browse home, project, skills
Provider-->>Picker: Document tree
统一上下文使用与压缩流程图flowchart TD
Request[Compose completion request]
Overhead[Estimate system prompt and tool overhead]
Messages[Estimate message tokens]
Observed[Read observed input tokens]
Usage[Use max estimated usage and observed input]
Decision{Compaction threshold reached}
Compact[ShouldCompact or ShouldSoftCompact]
Generate[Generate request]
Request --> Overhead
Request --> Messages
Overhead --> Usage
Messages --> Usage
Observed --> Usage
Usage --> Decision
Decision -->|yes| Compact
Decision -->|no| Generate
Compact --> Generate
极简模式提示词组装流程图flowchart TD
Load[Load AiBehaviorSettings]
Mode{minimal_mode enabled}
Minimal[Build MinimalSystemPrompt]
Full[Load templates and compose full system prompt]
Context[Prepare memory context]
Skills[BuildExtensionPrompt]
Request[Assemble completion request]
Load --> Mode
Mode -->|yes| Minimal
Mode -->|no| Full
Mode -->|learning_mode and not minimal_mode| Context
Mode -->|not minimal_mode| Skills
Minimal --> Request
Full --> Request
Context --> Request
Skills --> Request
文件级变更
可能关联的问题
提示与命令与 Sourcery 交互
自定义使用体验访问你的 控制面板:
获取帮助Original review guide in EnglishReviewer's Guide本 PR 将内部工作区升级为安全的 SAF DocumentsProvider 并接入系统目录选择器,同时新增极简提示词模式、统一上下文估算与自动压缩口径、修正 DeepSeek 推理请求协议、修复旧版 FTS4 索引导致的记忆删除失败,并发布 Android v1.3.3。 Sequence diagram for mounting the workspace in FilessequenceDiagram
participant User
participant Extensions
participant Channel
participant Picker
participant Provider
participant Workspace
User->>Extensions: MountWorkspace()
Extensions->>Channel: mountWorkspace
Channel->>Picker: ACTION_OPEN_DOCUMENT_TREE
Picker->>Provider: rootDocumentUri
Provider->>Workspace: queryRoots()
Provider-->>Picker: .linecode root
User->>Picker: Grant directory access
Picker->>Provider: queryChildDocuments()
Provider->>Workspace: Browse home, project, skills
Provider-->>Picker: Document tree
Flow diagram for unified context usage and compactionflowchart TD
Request[Compose completion request]
Overhead[Estimate system prompt and tool overhead]
Messages[Estimate message tokens]
Observed[Read observed input tokens]
Usage[Use max estimated usage and observed input]
Decision{Compaction threshold reached}
Compact[ShouldCompact or ShouldSoftCompact]
Generate[Generate request]
Request --> Overhead
Request --> Messages
Overhead --> Usage
Messages --> Usage
Observed --> Usage
Usage --> Decision
Decision -->|yes| Compact
Decision -->|no| Generate
Compact --> Generate
Flow diagram for minimal mode prompt assemblyflowchart TD
Load[Load AiBehaviorSettings]
Mode{minimal_mode enabled}
Minimal[Build MinimalSystemPrompt]
Full[Load templates and compose full system prompt]
Context[Prepare memory context]
Skills[BuildExtensionPrompt]
Request[Assemble completion request]
Load --> Mode
Mode -->|yes| Minimal
Mode -->|no| Full
Mode -->|learning_mode and not minimal_mode| Context
Mode -->|not minimal_mode| Skills
Minimal --> Request
Full --> Request
Context --> Request
Skills --> Request
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
你好——我发现了 1 个问题
给 AI 代理的提示
请处理本次代码审查中的评论:
## 单独评论
### 评论 1
<location path="platform/android/app/src/main/java/cn/lineai/platform/WorkspaceDirectoryProvider.java" line_range="267-270" />
<code_context>
+ @Override
+ public String moveDocument(String sourceDocumentId, String sourceParentDocumentId,
+ String targetParentDocumentId) throws FileNotFoundException {
+ if (ROOT_ID.equals(sourceDocumentId)
+ || !parentId(sourceDocumentId).equals(sourceParentDocumentId)) {
+ throw new FileNotFoundException("Invalid workspace move source");
+ }
+ File source = existingFile(sourceDocumentId);
</code_context>
<issue_to_address>
**issue (bug_risk):** `moveDocument` 在验证文档 ID 是否包含 `/` 之前调用了 `parentId(sourceDocumentId)`;当文档 ID 格式错误或由外部提供(例如 `"invalid"`)时,`lastIndexOf('/')` 会返回 `-1`,而 `substring(0, -1)` 会抛出 `StringIndexOutOfBoundsException`,而不是返回所要求的 `FileNotFoundException`。
**触发条件:** 外部 DocumentsProvider 客户端使用格式错误的源文档 ID 调用 `moveDocument` 时。
**建议修复:** 在推导父级 ID 之前,通过 `paths.resolve` 验证源 ID;或者让 `parentId` 使用 `FileNotFoundException` 拒绝不包含分隔符的 ID。
```suggestion
paths.resolve(sourceDocumentId);
if (ROOT_ID.equals(sourceDocumentId)
|| !parentId(sourceDocumentId).equals(sourceParentDocumentId)) {
throw new FileNotFoundException("Invalid workspace move source");
}
```
</issue_to_address>Sourcery 评估
需要人工审查。 首先需要处理 1 个发现的问题;此外,导出的 DocumentsProvider 改变了应用私有 .linecode 目录树的信任边界,并允许外部 SAF 客户端读取、修改、移动和删除其中的文件。授权或路径验证错误可能会暴露数据,或导致即使回滚版本也无法恢复的删除操作。除此之外,提示词、压缩和内存索引的更改会改变运行时行为,通常可以通过回滚并发布后续版本来修复。
阻塞性发现:platform/android/app/src/main/java/cn/lineai/platform/WorkspaceDirectoryProvider.java:270
Original comment in English
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="platform/android/app/src/main/java/cn/lineai/platform/WorkspaceDirectoryProvider.java" line_range="267-270" />
<code_context>
+ @Override
+ public String moveDocument(String sourceDocumentId, String sourceParentDocumentId,
+ String targetParentDocumentId) throws FileNotFoundException {
+ if (ROOT_ID.equals(sourceDocumentId)
+ || !parentId(sourceDocumentId).equals(sourceParentDocumentId)) {
+ throw new FileNotFoundException("Invalid workspace move source");
+ }
+ File source = existingFile(sourceDocumentId);
</code_context>
<issue_to_address>
**issue (bug_risk):** `moveDocument` calls `parentId(sourceDocumentId)` before validating that the document ID contains a `/`; a malformed or externally supplied ID such as `"invalid"` makes `lastIndexOf('/')` return `-1` and `substring(0, -1)` throws `StringIndexOutOfBoundsException` instead of returning the required `FileNotFoundException`.
**Triggers:** When an external DocumentsProvider client invokes `moveDocument` with a malformed source document ID.
**Suggested fix:** Validate the source ID through `paths.resolve` before deriving its parent, or make `parentId` reject IDs without a separator using `FileNotFoundException`.
```suggestion
paths.resolve(sourceDocumentId);
if (ROOT_ID.equals(sourceDocumentId)
|| !parentId(sourceDocumentId).equals(sourceParentDocumentId)) {
throw new FileNotFoundException("Invalid workspace move source");
}
```
</issue_to_address>Sourcery assessment
Needs a human reviewer. 1 finding to address first, and the exported DocumentsProvider changes the trust boundary around the app-private .linecode tree and lets external SAF clients read, modify, move, and delete its files; an authorization or path-validation mistake could expose data or cause deletions that reverting the release would not restore. The prompt, compaction, and memory-index changes otherwise alter runtime behavior that can normally be corrected by reverting and shipping a follow-up.
Blocking findings: platform/android/app/src/main/java/cn/lineai/platform/WorkspaceDirectoryProvider.java:270
Summary / 概述
把
dev上的 v1.3.3 改动合入master:内部工作区从「分享目录」升级为完整的系统文档提供者(SAF DocumentsProvider),新增「极简模式」,统一上下文用量与自动压缩的估算口径,修正 DeepSeek 思考档位请求体,并修复从旧版本升级的数据库删除记忆报no such module: fts4的问题。master包含 1 个提交(db3ada0)、38 个文件,+1116 / -276。versionCode37、versionName1.3.3;update.md已按既有版式补上## v1.3.3段落,发布工作流可直接切出。ACTION_OPEN_DOCUMENT_TREE+ 初始 URI 的交互;issue 里的「模型一键拉取」「多会话并行」不在本次范围内,因此没有写Closes。User-visible behavior / 用户可见行为
工作区与文件(对应 #23 第一节)
content://,点击只弹系统分享面板,看不到目录树.linecode根目录,provider 以DOCUMENTS_PROVIDER根注册,可被系统「文件」侧栏、MT 管理器等长期挂载home/、project/、skills/等子树exported="true"+android.permission.MANAGE_DOCUMENTS+DOCUMENTS_CONTENT_PROVIDERintent-filter,因此它同时出现在系统文件管理器的存储位置列表里。WorkspaceDocumentPaths,拒绝..、非法文件名、符号链接以及任何越出工作区根目录的路径;删除与复制前递归校验整棵子树,避免顺着链接操作到工作区之外(移动只是同目录改名,不递归内容,因此不需要该校验)。模型与提示词
@linecode_minimal_mode_enabled。开启后系统提示词压缩为一句角色说明 + 工具名清单,并跳过自定义提示词模板加载、记忆检索(learning_mode && !minimal_mode)与 Skills 扩展提示,适合小上下文模型或只想要它直接执行时。thinking,改为服务端支持的reasoning_effort——关闭 →none、中 →high、最高 →max(低/高沿用具体档位),自动档完全不发送该字段;自建与代理端点同样按模型识别生效。上下文与压缩
EstimateTextTokens()与EstimateContextTokens/SnapshotContext的additional_tokens、observed_input_tokens参数;上下文指示器与用量面板现在把系统提示词、工具定义的固定开销计入估算,并与服务端返回的输入 token 取较大值,而不是只统计消息文本、也不是实测覆盖估算。ShouldCompact/ShouldSoftCompact改用同一口径(本地估算 + 固定开销,与实测输入 token 取较大值);工具循环中途由ToolLoopCompactor估算同一份请求开销;对话为空且没有固定开销时不再触发。这样「消息不多但系统提示词 + 工具很大」也会按真实占用压缩。TokenUsageTracker从chat_composer的组件内UseState提升到chat_screen,通过ViewState.token_usage传给输入框与生成执行器;上下文快照缓存新增 overhead 与实测输入 token 两个失效维度,输入框重建时用量不再丢失。记忆
memories_fts索引,在当前运行时(SQLite 未编入 FTS3/4/5)无法读写,连DROP TABLE都失败。此前SqliteMemoryStore::Delete只容忍no such table,于是清理索引失败导致整个删除事务回滚并弹出no such module: fts4;现在把它识别为「不可达的派生索引」并跳过,记忆本身照常删除。实现要点 / Design
WorkspaceDirectoryProvider由ContentProvider重写为DocumentsProvider(queryRoots、queryDocument、queryChildDocuments、openDocument、createDocument、renameDocument、deleteDocument、copyDocument、moveDocument、isChildDocument,含可写标志、通知 URI、递归复制/删除与FileNotFoundException语义);新增包内工具类WorkspaceDocumentPaths;WorkspaceDirectoryShareService::OpenHome()改为MountWorkspace(),平台通道方法名同步为mountWorkspace。AiBehaviorSettings.minimal_mode及其仓储读写;PromptAssemblyContext新增可选回调on_context_overhead_estimated{},请求组装完成后回传系统提示词与工具定义开销;ContextCompactionService、auto_compaction_service、tool_loop_compactor增加context_overhead_tokens参数(带默认值,旧调用不受影响)。domain::EstimateTextTokens与上下文估算扩展;EmitDeepseek重写为受支持的档位映射;SqliteMemoryStore::Delete抽出IsUnreachableMemoryIndex(no such table/no such module)。default.properties与zh.properties同步新增极简模式文案、改写工作区按钮文案;tutorial_simple.md对应段落同步。Validation / 测试与验证
-j8—— 121/121:app:lintDebug成功,CIAndroid / lint and debug APK同样成功:app:assembleDebug成功,CI run 36753310512(commitdb3ada0)成功:app:testDebugUnitTest通过(新增WorkspaceDocumentPathsTest3/3,另含既有LocalDirectoryPathTest3/3;CI 目前不含该任务)Commands and environment used:
新增/扩写的覆盖:
tests/sqlite_memory_store_tests.cpp(升级库带不可达 FTS4 索引时删除记忆仍成功且记录消失,已确认修复前该用例失败)、tests/context_compaction_tests.cpp(硬/软触发在「估算 vs 实测取较大值」与固定开销下的边界)、tests/completion_protocol_codec_tests.cpp(DeepSeek 各档位请求体,含不发送thinking、自动档不发送reasoning_effort、代理端点)、platform/android/app/src/test/.../WorkspaceDocumentPathsTest.java(文档 ID 映射、越界与符号链接拒绝)。Design and safety checklist
ifchain.(端口改名、可选参数带默认值、标准DocumentsProvider接口)Screenshots or recordings
本次改动涉及两处界面:设置 → AI 行为的「极简模式 / Minimal mode」开关行,以及扩展 → Skills 详情里的「挂载工作区到文件系统」入口与随后的系统目录选择器。当前环境没有可用的设备或模拟器,未附前后对比图;如需要,我会在设备上补拍并更新本段。
CLA — required
CLA Signature: @LangLang03
Sourcery 摘要
升级工作区访问功能,新增 Minimal 模式,改进上下文使用量统计,并修复 DeepSeek 推理和旧版记忆删除兼容性问题。
新功能:
错误修复:
reasoning_effort值,替代不受支持的thinking请求字段。改进:
构建:
文档:
测试:
Original summary in English
Summary by Sourcery
Upgrade workspace access, add Minimal mode, improve context accounting, and fix DeepSeek reasoning and legacy memory deletion compatibility.
New Features:
Bug Fixes:
Enhancements:
Build:
Documentation:
Tests: