Skip to content

feat: 1.3.3 — 工作区挂载到文件系统、极简模式与记忆删除修复 - #36

Merged
LangLang03 merged 1 commit into
masterfrom
dev
Sep 30, 2026
Merged

LangLang03 merged 1 commit into
masterfrom
dev

Conversation

@LangLang03

@LangLang03 LangLang03 commented Sep 30, 2026 •

Copy link
Copy Markdown
Owner

Summary / 概述

把 dev 上的 v1.3.3 改动合入 master:内部工作区从「分享目录」升级为完整的系统文档提供者(SAF DocumentsProvider),新增「极简模式」,统一上下文用量与自动压缩的估算口径,修正 DeepSeek 思考档位请求体,并修复从旧版本升级的数据库删除记忆报 no such module: fts4 的问题。

  • 相对 master 包含 1 个提交(db3ada0)、38 个文件,+1116 / -276。
  • 版本:versionCode 37、versionName 1.3.3;update.md 已按既有版式补上 ## v1.3.3 段落,发布工作流可直接切出。
  • 关联 issue:Relates to [Feature Request] 工作区目录树管理、模型一键拉取与独立参数配置,及多任务并行处理(远期规划) #23。该 issue 的「一、工作区目录树文件管理(升级为 SAF DocumentsProvider)」在本 PR 完整落地,包括按钮改为「挂载工作区到文件系统」与 ACTION_OPEN_DOCUMENT_TREE + 初始 URI 的交互;issue 里的「模型一键拉取」「多会话并行」不在本次范围内,因此没有写 Closes。

User-visible behavior / 用户可见行为

工作区与文件(对应 #23 第一节)

之前 现在
入口 扩展 → Skills →「分享工作区目录」 「挂载工作区到文件系统 / Mount workspace in Files」
表现 基于 FileProvider 的临时 content://,点击只弹系统分享面板,看不到目录树 打开系统目录选择器并直接落在 .linecode 根目录,provider 以 DOCUMENTS_PROVIDER 根注册,可被系统「文件」侧栏、MT 管理器等长期挂载
能力 只能一次次重新分享路径 浏览、新建、重命名、复制、移动、删除 home/、project/、skills/ 等子树
  • 根目录注册:Manifest 中 provider 改为 exported="true" + android.permission.MANAGE_DOCUMENTS + DOCUMENTS_CONTENT_PROVIDER intent-filter,因此它同时出现在系统文件管理器的存储位置列表里。
  • 路径安全:文档 ID 与真实路径的映射集中到新的 WorkspaceDocumentPaths,拒绝 ..、非法文件名、符号链接以及任何越出工作区根目录的路径;删除与复制前递归校验整棵子树,避免顺着链接操作到工作区之外(移动只是同目录改名,不递归内容,因此不需要该校验)。

模型与提示词

  • 极简模式:「设置 → AI 行为」新增开关(学习模式上方),持久化键 @linecode_minimal_mode_enabled。开启后系统提示词压缩为一句角色说明 + 工具名清单,并跳过自定义提示词模板加载、记忆检索(learning_mode && !minimal_mode)与 Skills 扩展提示,适合小上下文模型或只想要它直接执行时。
  • DeepSeek 思考档位:请求体不再发送 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 两个失效维度,输入框重建时用量不再丢失。

记忆

  • 删除记忆报错修复:旧版 Android 版本用 FTS4 建的 memories_fts 索引,在当前运行时(SQLite 未编入 FTS3/4/5)无法读写,连 DROP TABLE 都失败。此前 SqliteMemoryStore::Delete 只容忍 no such table,于是清理索引失败导致整个删除事务回滚并弹出 no such module: fts4;现在把它识别为「不可达的派生索引」并跳过,记忆本身照常删除。

实现要点 / Design

  • platform:WorkspaceDirectoryProvider 由 ContentProvider 重写为 DocumentsProvider(queryRoots、queryDocument、queryChildDocuments、openDocument、createDocument、renameDocument、deleteDocument、copyDocument、moveDocument、isChildDocument,含可写标志、通知 URI、递归复制/删除与 FileNotFoundException 语义);新增包内工具类 WorkspaceDocumentPaths;WorkspaceDirectoryShareService::OpenHome() 改为 MountWorkspace(),平台通道方法名同步为 mountWorkspace。
  • application:AiBehaviorSettings.minimal_mode 及其仓储读写;PromptAssemblyContext 新增可选回调 on_context_overhead_estimated{},请求组装完成后回传系统提示词与工具定义开销;ContextCompactionService、auto_compaction_service、tool_loop_compactor 增加 context_overhead_tokens 参数(带默认值,旧调用不受影响)。
  • domain / infrastructure:domain::EstimateTextTokens 与上下文估算扩展;EmitDeepseek 重写为受支持的档位映射;SqliteMemoryStore::Delete 抽出 IsUnreachableMemoryIndex(no such table / no such module)。
  • resources:default.properties 与 zh.properties 同步新增极简模式文案、改写工作区按钮文案;tutorial_simple.md 对应段落同步。

Validation / 测试与验证

  • GoogleTest suite passes with Ninja and -j8 —— 121/121
  • Fake AI server tests pass —— 29/29
  • Android lint passes —— 本机 :app:lintDebug 成功,CI Android / lint and debug APK 同样成功
  • Android debug build succeeds —— 本机 :app:assembleDebug 成功,CI run 36753310512(commit db3ada0)成功
  • JVM 单元测试 —— :app:testDebugUnitTest 通过(新增 WorkspaceDocumentPathsTest 3/3,另含既有 LocalDirectoryPathTest 3/3;CI 目前不含该任务)
  • Verified on a device or emulator —— 本机没有连接设备/模拟器,未做视觉复核;本次 UI 改动是「新增一行开关」与「按钮文案/行为调整」,建议合入前在设备上补一次视觉检查并补截图

Commands and environment used:

cmake -S tests -B build/tests-ninja -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build/tests-ninja --parallel 8
ctest --test-dir build/tests-ninja --output-on-failure -j8          # 121/121 passed
python3 -m unittest tools/test_fake_ai_server.py                    # 29 tests OK
./platform/android/gradlew -p platform/android \
    :app:lintDebug :app:assembleDebug :app:testDebugUnitTest \
    --max-workers=8                                                 # BUILD SUCCESSFUL

新增/扩写的覆盖: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

  • The change keeps domain, application, infrastructure, platform, and presentation responsibilities separated.
  • New behavior is behind an abstraction or data-driven descriptor where extension is expected; it does not grow a UI if chain.(端口改名、可选参数带默认值、标准 DocumentsProvider 接口)
  • New or changed behavior has GoogleTest coverage.(另加 Android JVM 测试)
  • No credential, signing key, personal data, generated build output, or incompatible third-party code is included.
  • User-facing text is available in both English and Chinese where applicable.
  • UI changes preserve the intended LineCode behavior and have been visually checked.(仅新增开关行与按钮文案/行为调整;视觉复核待设备确认)

Screenshots or recordings

本次改动涉及两处界面:设置 → AI 行为的「极简模式 / Minimal mode」开关行,以及扩展 → Skills 详情里的「挂载工作区到文件系统」入口与随后的系统目录选择器。当前环境没有可用的设备或模拟器,未附前后对比图;如需要,我会在设备上补拍并更新本段。

CLA — required

CLA Signature: @LangLang03

Sourcery 摘要

升级工作区访问功能,新增 Minimal 模式,改进上下文使用量统计,并修复 DeepSeek 推理和旧版记忆删除兼容性问题。

新功能:

  • 将内部工作区作为完整的 SAF 文档提供程序公开,以便通过系统文件管理器浏览和管理文件。
  • 新增 Minimal 模式设置,该模式使用精简提示词,并跳过自定义提示词、记忆检索和 Skills 注入。

错误修复:

  • 使用 DeepSeek 支持的 reasoning_effort 值,替代不受支持的 thinking 请求字段。
  • 防止在升级后的数据库包含无法访问的旧版 FTS4 索引时,删除记忆失败。

改进:

  • 统一上下文使用量和压缩计算,将系统和工具开销纳入统计,并使用本地估算值与观测到的输入 token 数中的较大值。
  • 在聊天界面层级保留 token 使用量状态,使上下文指示器在输入组件重建后仍保持准确。

构建:

  • 将 Android 应用版本升级至 1.3.3(versionCode 37)。

文档:

  • 添加 v1.3.3 发行说明,并更新工作区和 Minimal 模式的用户指南。

测试:

  • 增加对安全工作区文档路径处理、DeepSeek 推理负载、上下文压缩阈值,以及从包含旧版 FTS4 索引的数据库中删除内容的测试覆盖。
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:

  • Expose the internal workspace as a full SAF document provider for browsing and managing files through system file managers.
  • Add a Minimal mode setting that uses a compact prompt and skips custom prompts, memory retrieval, and Skills injection.

Bug Fixes:

  • Use DeepSeek-supported reasoning_effort values instead of the unsupported thinking request field.
  • Prevent deletion of memories from failing when upgraded databases contain inaccessible legacy FTS4 indexes.

Enhancements:

  • Unify context usage and compaction calculations to include system and tool overhead and use the larger of local estimates and observed input tokens.
  • Preserve token usage state at the chat screen level so context indicators remain accurate across input component rebuilds.

Build:

  • Bump the Android application version to 1.3.3 (versionCode 37).

Documentation:

  • Add the v1.3.3 release notes and update workspace and Minimal mode user guidance.

Tests:

  • Add coverage for secure workspace document path handling, DeepSeek reasoning payloads, context compaction thresholds, and deletion from databases with legacy FTS4 indexes.

@sourcery-ai

sourcery-ai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

审阅者指南

本 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
Loading

统一上下文使用与压缩流程图

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
Loading

极简模式提示词组装流程图

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
Loading

文件级变更

变更 详情 文件
升级工作区暴露方式,使其成为可被系统文件管理器长期挂载和操作的 SAF 文档树。
  • 将 ContentProvider 改为支持根注册、查询、读写及 CRUD 的 DocumentsProvider。
  • 集中实现文档 ID 到工作区路径的安全映射,拒绝遍历、非法名称、符号链接和越界操作。
  • 将应用入口改为 ACTION_OPEN_DOCUMENT_TREE,并同步平台通道、服务接口、扩展页文案和教程。
  • 增加路径映射与越界/符号链接拒绝的 Android JVM 测试。
platform/android/app/src/main/AndroidManifest.xml
platform/android/app/src/main/java/cn/lineai/platform/WorkspaceDirectoryProvider.java
platform/android/app/src/main/java/cn/lineai/platform/WorkspaceDocumentPaths.java
platform/android/app/src/main/java/cn/lineai/platform/LineCodeWorkspaceDirectoryShareModule.java
platform/android/app/src/test/java/cn/lineai/platform/WorkspaceDocumentPathsTest.java
src/application/ports/workspace_directory_share.h
src/infrastructure/android_workspace_directory_share.cpp
src/presentation/screens/extensions_screen.cpp
resources/strings/default.properties
resources/strings/zh.properties
resources/raw/tutorial_simple.md
新增极简模式,并在提示词组装和上下文相关流程中应用该模式。
  • 新增设置模型、持久化键、仓储读写及中英文设置开关。
  • 极简模式生成紧凑系统提示词,并跳过自定义模板、记忆检索和 Skills 提示注入。
src/domain/behavior_settings.h
src/application/behavior_settings_repository.h
src/application/behavior_settings_repository.cpp
src/application/prompt_request_composer.h
src/application/prompt_request_composer.cpp
src/presentation/screens/llm_settings_screen.cpp
src/presentation/components/chat_generation_runner.cpp
resources/strings/default.properties
resources/strings/zh.properties
统一上下文用量估算、压缩触发和 UI 状态使用的 token 口径。
  • 将系统提示词与工具定义固定开销纳入文本/上下文估算。
  • 硬压缩、软压缩和工具循环中途压缩均使用本地估算与服务端实测输入 token 的较大值。
  • 将 TokenUsageTracker 提升到聊天页,并使上下文快照缓存随固定开销和实测 token 失效。
  • 补充固定开销、边界条件和估算/实测取大值的回归测试。
src/domain/context_usage.h
src/domain/context_usage.cpp
src/application/context_compaction.h
src/application/context_compaction.cpp
src/application/auto_compaction_service.h
src/application/auto_compaction_service.cpp
src/application/tool_loop_compactor.cpp
src/application/prompt_request_composer.cpp
src/application/token_usage_tracker.h
src/presentation/components/chat_composer.h
src/presentation/components/chat_composer.cpp
src/presentation/components/chat_generation_runner.cpp
src/presentation/screens/chat_screen.cpp
tests/context_compaction_tests.cpp
修正 DeepSeek 推理档位协议映射。
  • 移除 thinking 字段,改发送服务端支持的 reasoning_effort。
  • 处理自动档不发送字段,以及关闭、中、高/最高档位的映射。
  • 覆盖官方和代理端点的请求体行为。
src/infrastructure/openai_chat_codec.cpp
tests/completion_protocol_codec_tests.cpp
修复旧版 FTS4 索引导致的记忆删除失败。
  • 将 no such module 与 no such table 识别为不可达派生索引错误并跳过索引删除。
  • 保留记忆主体删除事务,并增加升级数据库回归测试。
src/infrastructure/sqlite_memory_store.cpp
tests/sqlite_memory_store_tests.cpp
发布 v1.3.3 并同步版本及变更日志。
  • 更新 Android versionCode/versionName。
  • 新增 v1.3.3 发布说明。
platform/android/app/build.gradle
update.md

可能关联的问题


提示与命令

与 Sourcery 交互

  • 触发新的审阅: 在 pull request 中评论 @sourcery-ai review。
  • 继续讨论: 直接回复 Sourcery 的审阅评论。
  • 根据审阅评论生成 GitHub issue: 回复审阅评论,请 Sourcery 根据该评论创建 issue。你也可以使用 @sourcery-ai issue 回复审阅评论,从中创建 issue。
  • 生成 pull request 标题: 在 pull request 标题的任意位置写入 @sourcery-ai,即可随时生成标题。你也可以在 pull request 中评论 @sourcery-ai title,以随时生成或重新生成标题。
  • 生成 pull request 摘要: 在 pull request 正文的任意位置写入 @sourcery-ai summary,即可在指定位置随时生成 PR 摘要。你也可以在 pull request 中评论 @sourcery-ai summary,以随时生成或重新生成摘要。
  • 生成审阅者指南: 在 pull request 中评论 @sourcery-ai guide,即可随时生成或重新生成审阅者指南。
  • 解决所有 Sourcery 评论: 在 pull request 中评论 @sourcery-ai resolve,即可解决所有 Sourcery 评论。如果你已经处理完所有评论且不想再看到它们,此功能非常实用。
  • 忽略所有 Sourcery 审阅: 在 pull request 中评论 @sourcery-ai dismiss,即可忽略所有现有的 Sourcery 审阅。如果你希望从新的审阅开始,这一功能尤其有用——别忘了评论 @sourcery-ai review 以触发新的审阅!

自定义使用体验

访问你的 控制面板:

  • 启用或停用审阅功能,例如 Sourcery 生成的 pull request 摘要、审阅者指南等。
  • 更改审阅语言。
  • 添加、删除或编辑自定义审阅说明。
  • 调整其他审阅设置。

获取帮助

Original review guide in English

Reviewer's Guide

本 PR 将内部工作区升级为安全的 SAF DocumentsProvider 并接入系统目录选择器,同时新增极简提示词模式、统一上下文估算与自动压缩口径、修正 DeepSeek 推理请求协议、修复旧版 FTS4 索引导致的记忆删除失败,并发布 Android v1.3.3。

Sequence diagram for mounting the workspace in 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
Loading

Flow diagram for unified context usage and compaction

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
Loading

Flow diagram for minimal mode prompt assembly

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
Loading

File-Level Changes

Change Details Files
升级工作区暴露方式,使其成为可被系统文件管理器长期挂载和操作的 SAF 文档树。
  • 将 ContentProvider 改为支持根注册、查询、读写及 CRUD 的 DocumentsProvider。
  • 集中实现文档 ID 到工作区路径的安全映射,拒绝遍历、非法名称、符号链接和越界操作。
  • 将应用入口改为 ACTION_OPEN_DOCUMENT_TREE,并同步平台通道、服务接口、扩展页文案和教程。
  • 增加路径映射与越界/符号链接拒绝的 Android JVM 测试。
platform/android/app/src/main/AndroidManifest.xml
platform/android/app/src/main/java/cn/lineai/platform/WorkspaceDirectoryProvider.java
platform/android/app/src/main/java/cn/lineai/platform/WorkspaceDocumentPaths.java
platform/android/app/src/main/java/cn/lineai/platform/LineCodeWorkspaceDirectoryShareModule.java
platform/android/app/src/test/java/cn/lineai/platform/WorkspaceDocumentPathsTest.java
src/application/ports/workspace_directory_share.h
src/infrastructure/android_workspace_directory_share.cpp
src/presentation/screens/extensions_screen.cpp
resources/strings/default.properties
resources/strings/zh.properties
resources/raw/tutorial_simple.md
新增极简模式,并在提示词组装和上下文相关流程中应用该模式。
  • 新增设置模型、持久化键、仓储读写及中英文设置开关。
  • 极简模式生成紧凑系统提示词,并跳过自定义模板、记忆检索和 Skills 提示注入。
src/domain/behavior_settings.h
src/application/behavior_settings_repository.h
src/application/behavior_settings_repository.cpp
src/application/prompt_request_composer.h
src/application/prompt_request_composer.cpp
src/presentation/screens/llm_settings_screen.cpp
src/presentation/components/chat_generation_runner.cpp
resources/strings/default.properties
resources/strings/zh.properties
统一上下文用量估算、压缩触发和 UI 状态使用的 token 口径。
  • 将系统提示词与工具定义固定开销纳入文本/上下文估算。
  • 硬压缩、软压缩和工具循环中途压缩均使用本地估算与服务端实测输入 token 的较大值。
  • 将 TokenUsageTracker 提升到聊天页,并使上下文快照缓存随固定开销和实测 token 失效。
  • 补充固定开销、边界条件和估算/实测取大值的回归测试。
src/domain/context_usage.h
src/domain/context_usage.cpp
src/application/context_compaction.h
src/application/context_compaction.cpp
src/application/auto_compaction_service.h
src/application/auto_compaction_service.cpp
src/application/tool_loop_compactor.cpp
src/application/prompt_request_composer.cpp
src/application/token_usage_tracker.h
src/presentation/components/chat_composer.h
src/presentation/components/chat_composer.cpp
src/presentation/components/chat_generation_runner.cpp
src/presentation/screens/chat_screen.cpp
tests/context_compaction_tests.cpp
修正 DeepSeek 推理档位协议映射。
  • 移除 thinking 字段,改发送服务端支持的 reasoning_effort。
  • 处理自动档不发送字段,以及关闭、中、高/最高档位的映射。
  • 覆盖官方和代理端点的请求体行为。
src/infrastructure/openai_chat_codec.cpp
tests/completion_protocol_codec_tests.cpp
修复旧版 FTS4 索引导致的记忆删除失败。
  • 将 no such module 与 no such table 识别为不可达派生索引错误并跳过索引删除。
  • 保留记忆主体删除事务,并增加升级数据库回归测试。
src/infrastructure/sqlite_memory_store.cpp
tests/sqlite_memory_store_tests.cpp
发布 v1.3.3 并同步版本及变更日志。
  • 更新 Android versionCode/versionName。
  • 新增 v1.3.3 发布说明。
platform/android/app/build.gradle
update.md

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

你好——我发现了 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


Sourcery 对开源项目免费——如果您喜欢我们的审查结果,请考虑分享 ✨
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


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

@LangLang03
LangLang03 merged commit 991f370 into master Sep 30, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant