fanlusky
663f72301d
fix(server): 独立上屏的整句候选也落库
...
上一个提交改的是 InputSession::commit(),而 Windows 前端根本不走那条路:选词由
ProcessSelectionKey 自己驱动。那里 CandidateSource::Generated 走提前返回,落库的
闸门 ShouldStoreEarlyReturnPhrase 要求造词前缀非空,也就是只认"先选前缀、再用整句
收尾"这一种形状;用户直接选一条完整的整句时 creating_word 没激活,条件为假,什么
也不做就返回了。Google 解码器那条整句(Fallback)不在提前返回的名单里,走普通
路径,但同样没有行可以调频。
因此拆出 ShouldStoreStandaloneSentence:整句候选独立上屏时就该落库,带 7 音节
上限(对标 quanpin::WordLatticeOptions::max_phrase_syllables)。接在造词前缀
后面的那一支由用户一段段选出来,维持原样不设限。
顺带修掉同一处的读音拼接:前缀为空时不能带上那个分隔符,'na'yi'tiao 这种前导
撇号会让整条读音作废。
原先有一条测试把这个缺陷钉住了(断言没有前缀就不落库),按新的意图翻过来。
2026-09-19 13:48:26 +08:00
fanlusky
ccbaa3a631
fix(engine): 送进 Google 解码器前把 ü 换成 nue/lue/ju 写法
...
小鹤双拼 ntdddswu 出的是「女蛾黛动物」而不是「虐待动物」:nt 转成全拼后
是 nve(shuangpin_pinyin_set 把 nue 抹掉了,词库与词格那一侧统一用 v 形),
而本地 googlepinyinime-rev 的拼写表和 inputtools 云输入都不认 nve/lve/jv,
只有 nue/lue/ju/jue,也不做 v→ü 的转写。带分隔符的串照样送过去了,解码器
却把 nve 重新切成 nv + e,于是有了「女蛾」。
加一个 quanpin::to_google_spelling,按音节整体改写 nve→nue、lve→lue、
jv→ju 这一类拼写,只在两个 Google 解码器的边界上用:云输入的 query_text、
双拼与全拼的整句回退。词库查询和词格用的仍然是 canonical_syllable 那一侧的
v 形写法,没有动。nv'er、lv'se 这些 Google 也认的写法原样通过。
2026-09-19 12:29:01 +08:00
Ouchihao
5e641fb5a0
fix(engine): accept yo as a complete shuangpin syllable
2026-09-18 20:35:14 +08:00
Lu Fan(SonnyCalcr)
4dea1cd12f
Merge pull request #420 from metasequoiaime/feat/ctrl-arrows-segment-caret
...
feat(input): 组词内按分词的光标与删除(#35 / #187 / #347)
2026-09-18 12:35:52 +08:00
Jia Sui
809f700998
test(server): 覆盖微软双拼 ';' 尾键的分段边界
...
- nihkb;(你好病 = ni|hk|b;)断言 {0,2,4,6}:';' 归属它开始的音节
- nihcb; 断言 {0,2,3,5,6}:贪心最长配对是契约,'cb' 是有效微软编码
(cou),按段删除跟随 preedit 显示的同一条切分
Refs #187
2026-09-18 08:59:19 +08:00
Jia Sui
b1ec3ab1e0
feat(server): Ctrl+Backspace 按分词删除前置拼音(#187)
...
组词中 Ctrl+Backspace 删除光标前的一个分词单元:剩余拼音非空时删
最后一个字的拼音(音节段),剩余拼音为空时删除最后一段已选分词。
engine:
- InputSession::segment_raw_boundaries() 作为按段删除/移动的唯一分段来源:
全拼把纠错显示串的分隔符映回 raw 下标,双拼与 pinyin_segmentation 共用贪心谓词,
2 字辅助码自成一段;非拼音方案与本地模式返回空表示无单位模型
server:
- IsSegmentBackspaceKey(Ctrl-only)、整段丢弃 / 边界截断 / 单字符回退三分支,
截断点残留分隔符清理
- 复用 CompositionRestored 回包(含 caret),仅协商能力位且非 UiLess 时发送;
新出现「只剩已选汉字、无拼音」的中间态
windows:
- 两处 Ctrl 闸门对组词中的 Ctrl+VK_BACK 放行,新增 FUNCTION_BACKSPACE_SEGMENT
与 _HandleCompositionBackspaceSegment(读回包重建,失败回退单字符)
- 空 raw 状态渲染、终态清理 word_for_creating_word,延迟投影失效处理
Closes #187
2026-09-17 23:01:31 +08:00
fanlusky
bc37ac9a9e
feat(installer): 安装时可自定义数据目录位置
...
词库、用户配置和皮肤此前固定在 %LOCALAPPDATA%\metasequoiaime,整包几百 MB
全压在 C 盘。安装向导新增一页,允许把这部分数据放到任意盘。
程序本体仍固定装在 Program Files:MetasequoiaImeServer.exe 带 uiAccess=true,
只有在受信任目录里这个标志才生效。
运行期的权威来源是 HKLM\Software\Metasequoia\MetasequoiaIME 的 DataDir。
Server、TSF DLL 和引擎三个组件各自按同一顺序解析:METASEQUOIA_IME_DATA_DIR
环境变量 -> 该注册表值 -> %LOCALAPPDATA%\metasequoiaime。三处各持一份实现,
因为组件边界规则禁止 windows/ 与 server/ 互相 include。32 位 TSF DLL 用
KEY_WOW64_64KEY 读,避开 WOW64 重定向。
安全相关的两个约束:
- 安装器在数据目录里写 .metasequoiaime-data 标记。覆盖安装的清理和卸载的整目录
删除只在看到这个标记(或目录就是历史默认位置)时才执行——用户可能把数据目录
指到一个本来就有自己文件的文件夹。
- 选择页与 /DATADIR= 走同一套校验:拒绝相对路径、盘符根目录、不存在的盘、程序
目录内部,以及 Windows/Program Files/各 AppData/用户主目录本身。
升级时改了位置,PrepareToInstall 在停掉输入法进程后用 robocopy /MOVE 搬运用户
拥有的数据(msime_user.db 及其 WAL/SHM/journal、config.toml、config.base.toml、
skins\),词库和前端资源由本次安装重新写入。跨卷移动目录 MoveFile 会失败,所以用
robocopy。用户词库搬运失败会中止安装:否则新版本对着空的 msime_user.db 启动,
ssPostInstall 的回放只记一句 skipped,用户的自造词就静悄悄没了。
测试侧新增 METASEQUOIA_IME_CONFIG_DIR,只改 config.toml 的位置而不搬词库。原先
靠重定向 LOCALAPPDATA 做隔离的办法在装了正式版的机器上已不再成立——注册表值
的优先级高于它。
2026-09-17 22:49:19 +08:00
Jia Sui
e64195731e
feat(server): Backspace 删空剩余拼音后退选已选分词(#35)
...
已选分词是造词中间态:删空剩余拼音时不再整条 composition 丢弃,
而是退选最后一段并恢复其原始拼音与候选。
engine:
- SelectionTransition 暴露本次选择消费掉的原始输入(保留大小写与双拼按键)
engine/contracts:
- 新增回复类型 CompositionRestored=14 与能力位 CompositionRestore;
MaxKnown 同步抬高,Server 按协商能力位门控发送,旧 DLL 不会收到未知帧
server:
- 造词中间态压 (consumed_raw, previous_creating_word) 快照,边界 Backspace 弹栈退选
- 任何清空 raw 的路径同时清 creating_word 与快照历史,避免跨 composition 泄漏
windows:
- _HandleCompositionBackspace 提示退选时读回包重建 keystroke buffer / word / 预编辑 / 光标
- NeedToCreateWord 与 CompositionRestored 共用载荷解析;旧 Server 与 UiLess 回退旧行为
Closes #35
2026-09-17 18:45:01 +08:00
Jia Sui
a3b1e4380c
feat(server): 模糊音首次启用播种规则并持久化标记
...
总开关默认关不变;出厂态(fuzzy_seeded 未置位)第一次开总开关时,用一次
WriteConfiguredValues 批量写 13 键(总开关 + 11 规则全 true + 播种标记),
单文件原子写无部分失败态。标记置位后总开关任何翻动只写总开关一个键,
用户修剪过的选择在临时停用/恢复间原样保留。
播种信号靠持久化标记而不是「规则位全零」:用户故意全部取消勾选后位图
同样是零,无标记会把每次开启都误判成首次启用。fuzzy_seeded 是内部键,
设置快照不下发不展示;两份 toml 模板补键,缺键会被升级合并丢弃导致
老用户升级后误重播种。设置页勾选态由 host 处理 configUpdate 后重发的
configSnapshot 驱动,前端无播种逻辑。
新增首次播种用例(播种全开、修剪子集反复开关、重启保持、全取消后不
重播种);默认值三形态补标记断言;既有往返/门控/注入用例改走不门控
视图或规则键直设,避开播种路径保持用例意图纯净。
2026-09-13 09:33:14 +08:00
Jia Sui
b807f50d69
feat(server): 模糊音增加总开关并在聚合 getter 门控
...
[input] 新增 fuzzy_pinyin 总开关,默认关;GetConfiguredFuzzyPinyinOptions
在总开关关时返回全零 options,规则位缓存保留,临时停用后重开立即恢复。
设置页快照改用不门控的规则位视图,总开关关闭时复选框仍展示已存勾选;
configUpdate 分发把精确分支 input.fuzzy_pinyin 排在 fuzzy_ 前缀分支之前。
注入用例改为带总开关的 A-B-A-B,新增门控与默认值断言。
2026-09-13 09:12:45 +08:00
Jia Sui
feb7db6de4
feat(server): 模糊音规则接入配置与会话注入
...
- [input] 段新增 11 个平铺模糊音键(fuzzy_z_zh … fuzzy_uan_uang,默认全关),
读取用固定键表驱动,键名即 FuzzyPinyinRule 枚举名小写,单一映射可评审;
位掩码缓存 uint32,reload 先清零再按位合成
- GetConfiguredFuzzyPinyinOptions 合成引擎选项,SetConfiguredFuzzyPinyinRule
按键写盘(未知名拒绝且不动位图), ApplyConfiguration 每键注入,
全拼与双拼同路径生效,设置改动即时生效
- settings_app configSnapshot 补 11 字段,ApplyConfigUpdate 用 input.fuzzy_
前缀分发;windows_webview2 死宿主不接线(InitWebviewSettingsWnd 零调用者)
- 测试:默认值三形态、逐键往返与 0x7ff 合成、未知键拒绝、
全拼/双拼 zhang→zang 候选注入用例;开发模板同步 11 键
2026-09-13 08:35:25 +08:00
fanlusky
aba4851f90
test: do not require a lattice sentence from the locked dictionaries
...
Whether a whole-sentence candidate is produced depends on which
dictionaries and local models are installed, so the CI product data
yields none and the presence requirement failed there. Check the
canonical reading of whatever whole-sentence candidates do appear, and
assert the shuangpin-to-quanpin conversion unconditionally instead --
that conversion is the value the fix attaches to those candidates.
2026-09-12 16:01:42 +08:00
fanlusky
e835e09c20
fix(engine): give whole-sentence fallback candidates a canonical pinyin
...
The Google-pinyin whole-sentence candidate is inserted at index 0 in both
quanpin and shuangpin, so it is what Space commits. All four construction
sites built it without a canonical quanpin reading, so when it finished a
word-creation session update_creating_word_progress() had no reading to
join and can_store stayed false: the prefix plus the sentence went to the
host app but were never learned.
Carry the converted quanpin segmentation on those candidates, and extract
the early-return storage condition into a testable predicate.
2026-09-12 15:53:54 +08:00
fanlusky
a7779d2b05
refactor(engine): 将 engine 从 submodule 内嵌为仓内一等组件
...
`vendor/MetasequoiaImeEngine` submodule 改为 `engine/` 目录,导入的是
product-lock.json 原本钉住的提交 c810d201,逐文件核对过 blob,因此这是一次
搬迁而不是引擎升级。引擎自己的嵌套 submodule(googlepinyinime-rev、utfcpp、
miniaudio)按各自 gitlink 一并展开,来源与提交见 engine/UPSTREAM.md。
Windows 专门化裁掉了不属于本产品的部分:whisper.cpp 与本地推理 provider、
macOS 示例宿主、整个 dictionary/ 建库流水线、上游 CI 与 release-please 配置。
词库仍按 product-lock.json 在构建时取发布产物。
引擎不再进 product-lock.json:没有 gitlink 就没有可比对的东西,锁里写一个上游
commit 等于宣称这棵树仍等于上游,而第一个 Windows 专门化改动落地时这句话就假了。
verify-contracts / verify-checkout 随之移除,verify-published 保留。
CI 与工具链:引擎源码并入根 scripts/format.sh(删掉引擎自己的那份,避免两套排除
列表分叉);引擎 voice.yml 里的 silero_vad.onnx 摘要校验移到本仓 lock job;
engine-bump-triage 工作流与其测试删除;gitsubmodule 的 dependabot 频率由 daily
改为 monthly。
README、README.en、AGENTS.md、CONTRIBUTING、docs/product-release.md 及各子目录
文档同步说明新的位置与边界。
2026-09-12 03:40:48 +08:00
Evan
688972b28c
Merge remote-tracking branch 'origin/main' into pr184-merge
...
# Conflicts:
# server/src/session/input_session.h
2026-09-06 15:31:05 +09:00
Evan Hu
ac805078e4
refactor(server): carry engine online queries through asynchronous candidate tasks
2026-09-06 13:24:03 +09:00
Evan Hu
a533d5aa2b
Merge remote-tracking branch 'origin/main' into chore/oss-hardening
...
# Conflicts:
# AGENTS.md
2026-09-06 13:06:54 +09:00
Evan
42238a2af6
style: 用 .clang-format 重排 server / windows / ui / log
...
一次性重排,无任何行为改动。四个目录各自的 .clang-format 放在仓库里已久,但全组织只有
MSIME-Linux 在 CI 里执行 clang-format 检查,这边 149 个文件里有 149 个不符合自己声明的风格。
已逐文件核对语义等价:去掉空白、注释与相邻字符串字面量拆分之后,全部 149 个文件与重排前逐字节
相同。差异只有三类——缩进与换行、clang-format 补的 } // namespace 结尾注释、以及长字符串被拆成
相邻字面量(C++ 保证自动拼接)。
这个提交会写进 .git-blame-ignore-revs。
2026-09-06 12:13:47 +09:00
Evan
2b8bf937d9
fix(server): adopt isolated engine sessions and helpcode annotations ( #178 )
2026-09-06 11:44:30 +09:00
Ouchihao
2af10f56aa
fix(candidates): honor English ranking in mixed input
2026-09-05 16:40:31 +08:00
fanlusky
5da93af45c
Optimize Japanese queries.
2026-08-22 12:03:55 +08:00
fanlusky
8565b0531b
Add kaomoji to mixed candidates (after emoji) behind general.kaomoji_mixed_input
...
kaomoji_ime: async worker mirroring emoji_ime; KaomojiQuery::QueryPrefix
gains a db_path override. NormalizeMixedCandidateOrder places kaomoji right
after emoji, shifting with cloud/AI. event_listener wires
UpdateKaomojiInput/ApplyKaomojiCandidates/EnqueueKaomojiCandidates and the
PrepareCandidateList trigger; config general.kaomoji_mixed_input is plumbed
through settings_app/webview2; main.cpp starts/stops KaomojiIme; ordering test
added.
2026-08-17 00:08:24 +08:00
fanlusky
d15319bd66
Add emoji to mixed candidates (slot 3, shifts with cloud/AI) behind general.emoji_mixed_input.
2026-08-16 19:29:52 +08:00
fanlusky
d9a7235919
Do not segmentation for help code part.
2026-08-16 03:04:02 +08:00
fanlusky
2bc321ecfb
Add uppercase-first reverse auxiliary-code matching with dedicated caching for Shuangpin.
2026-08-16 02:40:14 +08:00
fanlusky
29242b2641
Also add short english words to cands.
2026-08-09 18:37:04 +08:00
fanlusky
28b7f174e6
Fix the issue where words created from cloud candidates cannot be deleted.
2026-08-04 02:50:05 +08:00
fanlusky
b7f17facfa
Expand the range of the candidate window font size setting slightly.
...
Fix the issue where AI predictions cannot be directly committed and instead trigger word-creation mode, and fix the issue where words generated by AI predictions cannot be deleted via right-click.
2026-08-03 00:07:20 +08:00
fanlusky
f70d210465
In auxiliary code mode, AI prediction should not send requests, just like cloud prediction.
2026-07-31 16:12:03 +08:00
fanlusky
4994aa884a
fix(candidate): prefetch initial candidates before partial last page
...
Expand limited single-letter candidates before entering a partially filled
last page so pagination advances normally and the page is full on first display.
2026-07-29 22:23:33 +08:00
fanlusky
2983594211
test(shuangpin): cover multi-syllable suggestion storage
...
Add regression coverage for storing multi-syllable cloud and AI candidates
from their raw shuangpin sequence.
2026-07-29 20:45:28 +08:00
fanlusky
a033f9d2c2
feat(composition): support phrase creation from incomplete pinyin
...
- continue phrase creation for abbreviated quanpin and shuangpin input
- preserve manual segmentation boundaries in the remaining input
- restrict helpcode detection to complete unsegmented pinyin
- accumulate and validate canonical pinyin before phrase insertion
- route completed phrases through canonical-pinyin storage
- add coverage for abbreviations, manual segmentation, and helpcodes
2026-07-29 19:53:21 +08:00
fanlusky
02d5a3ff37
fix(candwnd): measure and size candidate wrap at 600 DIP
...
Force wrap-aware measure, serialize FineTune after measure content
updates, and preserve flip-up host height via MarginTop.
feat: lazily load single-letter Pinyin candidates
- query the top 24 single-letter candidates from the database
- load the complete candidate list on the first page-down action
- apply the same behavior to Shuangpin and Quanpin
- resolve Shuangpin initials according to the active profile
- preserve candidate frequency adjustment and pinning
- disable deletion for single-letter candidates
- add regression tests for Shuangpin v-to-zh mapping and lazy expansion
2026-07-27 16:12:46 +08:00
fanlusky
4f859d012f
fix: stabilize AI/cloud candidate apply to restore paging and prevent duplicate 🤖
...
Skip async AI/cloud refresh on paging and selection keys, early-exit when the
suggestion is already in the list, and dedupe series-cache inserts so repeated
cache hits no longer reset page_index or accumulate AI rows.
2026-07-24 00:37:23 +08:00
fanlusky
4765d72156
Integrate the handwriting recognition board into the server.
2026-07-20 01:57:31 +08:00
fanlusky
985ec87ea2
Add support for the Ziranma Shuangpin scheme.
2026-07-15 00:26:07 +08:00
fanlusky
c325828bc9
Add a cloud icon to cloud candidates.
2026-07-11 10:52:38 +08:00
fanlusky
e3317a248e
Fix the issue where cloud prediction for engine and shuangpin is not stored in the database.
2026-06-25 23:21:28 +08:00
fanlusky
2463d5486c
The engine backend should also cache cloud prediction results, and ensure that filtering with auxiliary codes is consistent with legacy behavior.
2026-06-23 07:26:03 +08:00
fanlusky
b956e0d453
Fix the issue where the auxiliary code is not cleared during full-pinyin word creation.
2026-06-22 20:49:19 +08:00
fanlusky
2d41bbb6c4
Fix the preedit behavior during full-pinyin word creation.
2026-06-22 12:37:55 +08:00
fanlusky
9c5127af98
Quanpin support creating words.
2026-06-22 01:32:40 +08:00
fanlusky
77af7d7f26
Do not trigger cloud prediction when the full-pinyin auxiliary code is active.
2026-06-22 00:56:59 +08:00
fanlusky
fca15d898d
Add tests
2026-06-20 22:11:00 +08:00