Skip to content

fix: guard embedding inputs and isolate rejected batches (MEMMY-488) - #602

Open
whqf1123 wants to merge 15 commits into
MemTensor:v1.2.4from
whqf1123:fix/memmy-488-embedding-input-guard
Open

whqf1123 wants to merge 15 commits into
MemTensor:v1.2.4from
whqf1123:fix/memmy-488-embedding-input-guard

Conversation

@whqf1123

Copy link
Copy Markdown

MEMMY-488

云效:https://devops.aliyun.com/projex/bug/aee64741d4589c77df0cc2e3b8

修复 OpenAI-compatible 第三方 embedding 模型长度估算不足,以及输入类错误导致正常记忆与异常记忆整批失败的问题。

改动

  • 对无法确定原生分词器的模型别名,保留 token 预算并增加默认 12,000 UTF-8 字节的分块保护,可通过 maxInputBytes / MEMMY_EMBEDDING_MAX_INPUT_BYTES 调低。完整保留输入,不切坏 Unicode 字符;已知 OpenAI 模型维持现有 token 路径。
  • 新任务及历史 embedding 重试队列遇到输入类 HTTP 400/413/422(包括 20015 参数无效)后逐条隔离,正常条目保存向量,异常项独立失败,确定性错误不反复重试。
  • 认证、限流、服务端错误不触发逐条请求放大。增加配置与回归测试,更新配置迁移和文档。

验证(同步 v1.2.2 后,HEAD 52b2fdf)

  • 已 merge 公司 v1.2.2(f6c93382),无冲突;相对目标分支仅 11 个 MEMMY-488 相关文件有差异。
  • Memory 全量测试:1,135 通过、1 失败、1 跳过;lint、typecheck、build 通过。失败项为 project-version.test.ts:期望 2.1.3,但当前为 2.1.4;测试及版本文件与目标分支完全一致,未为此修改无关测试。
  • 基于该 HEAD 重新构建 macOS arm64 / intl 应用(应用内版本 1.2.1),用 hdiutil 制作新的本地未签名 DMG,已成功挂载并复制到用户可写目录。构建产物、DMG 与复制副本的可执行文件、app.asar 和两处修复核心模块 SHA-256 一致。
  • 使用新 DMG 副本内的 Electron 可执行文件及 Memory 模块执行 4 项回归:27,447 字符英文分为 3 块、中文/emoji 分为 8 块,均完整保留原文且每块不超过 12,000 UTF-8 字节;新任务及重试队列均为 3 条正常成功、1 条异常独立失败,继续调度没有重复无效请求。测试使用临时数据库与模拟供应商响应。
  • 新 DMG:Memmy-1.2.1-MEMMY-488-v122-52b2fdf1-arm64-intl-local-test.dmg
  • DMG SHA-256:c5821ff05f559429a38e81c6623a5fee64fb0a9ba6d36c6408af2dd538dd8262

已知限制与待验收项

  • 本地测试 DMG 使用官方 Electron 应用配置及系统 hdiutil 封装;官方 OCU 启动检查超时且公司电脑无法授予所需权限,替代构建仅验证官方组件签名及复制一致性,未验证操控功能。替代脚本不进入本 PR,正式打包脚本未修改。
  • 未验证真实供应商的原始 27,446/27,447 字符边界;12,000 字节是保守默认值,不保证未知模型的所有上下文限制。
  • 新应用窗口检查:Computer Use 读取指定副本窗口超时;本机有多个同 bundle ID 的副本,无法确认新副本已显示欢迎界面。包内模拟回归通过不等于 GUI 启动或登录后的端到端验收通过;未验证签名、公证或其他操作系统。
  • 同步前全项目检查未全绿(不是新 HEAD 的全项目复测):后端2项、前端3项、桌面11项、打包2项失败;失败测试文件在未修改基线上同样复现,涉及地区配置、活动文案、桌面升级与执行环境权限等。
  • 更新代码不会自动恢复历史失败记忆,需明确执行重试或重建索引。分块向量仍沿用原有加权合并方式。

Anson-Se and others added 15 commits September 26, 2026 13:17
…mand

A turn routed as end_topic used to be dropped from L1 capture as a whole,
so feedback, work conventions and instructions sent together with the
closing words never reached L1, user memory or the episode reward.

Only a bare end-topic command ("结束会话" / "不聊了") is still kept out of
L1. Every other end_topic turn now goes through the same capture decision
as a normal turn; the closed episode waits for that decision before
reflection and reward are queued.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every memmy-memory run reports memmy_cli_* events to the cloud analytics
endpoint. resolveCommandIdentity took the second positional word as
command_action unconditionally, which was meant for subcommands such as
`session close`. For search, add, get and delete that word is the search
query, the memory text or the memory id, so it was sent verbatim. An
unrecognized first word was also sent verbatim as command_group.

command_action is now reported only when the first word is a group with
subcommands (service, session, turn, raw) and the second word is one of
that group's known subcommands; raw methods match case-insensitively, as
runRaw does. An unrecognized first word is reported as command_group
"unknown". The known commands live in a small table in analytics.ts that
mirrors runCommand and mapTopLevelCommand. has_session_id and has_turn_id
are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The session close route only woke the auto worker when the close result
listed closed episodes, jobs, or scheduled evolution. For an L3 World
Model v2 session, closeSession also freezes the pending L3 evidence
batches and queues l3_world_model_update jobs, but it does not return
them. When the session's episode had already closed earlier (idle
timeout or end_topic), closedEpisodeIds was empty and nothing woke the
worker. The worker does not poll, so the new L3 jobs stayed queued until
an unrelated request happened to wake it.

The close route now always schedules the worker, as the token compaction
boundary already does after freezing batches. A close with no follow-up
work costs one empty drain. A new REST contract test closes an L3 v2
session whose episode had already ended and checks that the worker picks
up the frozen L3 job.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-worker

fix(memory): wake the worker after every session close
v1.2.2 requires the turn capture decision to return a non-empty l1.title
together with l1.summary. The mixed feedback-and-closing test stub only
returned a summary, so the capture decision threw and the closing L1 stayed
in resolving instead of being activated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…and-action

fix(memory): stop sending CLI arguments as analytics command actions
fix(memory): stop dropping end-topic turns that carry feedback from L1
Synchronize the latest code from the main branch to v1.2.2
…-format

fix: 兼容 LM Studio 的 JSON 响应格式
…upgrade-v1.2.2

fix(memory): replace stale runtimes by build identity
@syzsunshine219
syzsunshine219 changed the base branch from v1.2.2 to v1.2.3 October 12, 2026 12:45

This branch has not been deployed

No deployments
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.

5 participants