`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 及各子目录 文档同步说明新的位置与边界。
94 lines
3.7 KiB
Python
94 lines
3.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Generate the C++ punctuation contract from policy.json."""
|
|
import argparse
|
|
import json
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parent
|
|
SPEC = json.loads((ROOT / "policy.json").read_text(encoding="utf-8"))
|
|
simple = SPEC["simple"]
|
|
alternating = SPEC["alternating"]
|
|
nested = SPEC["nested"]
|
|
inputs = [entry["input"] for entry in simple + alternating] + [nested["openingInput"], nested["closingInput"]]
|
|
if (SPEC["contractVersion"] != 1 or any(len(value) != 1 or not 32 <= ord(value) < 127 for value in inputs) or
|
|
len(set(inputs)) != len(inputs)):
|
|
raise SystemExit("Invalid punctuation contract")
|
|
|
|
|
|
def char_literal(value):
|
|
return "'" + value.replace("\\", "\\\\").replace("'", "\\'") + "'"
|
|
|
|
lines = [
|
|
"// Generated by contracts/punctuation/generate.py; edit policy.json instead.",
|
|
"#pragma once",
|
|
"#include <array>",
|
|
"#include <string_view>",
|
|
"",
|
|
"namespace metasequoia::punctuation_contract",
|
|
"{",
|
|
f"inline constexpr int version = {SPEC['contractVersion']};",
|
|
"struct Mapping",
|
|
"{",
|
|
" char input;",
|
|
" const char *output;",
|
|
"};",
|
|
"struct AlternatingMapping",
|
|
"{",
|
|
" char input;",
|
|
" const char *opening;",
|
|
" const char *closing;",
|
|
"};",
|
|
f"inline constexpr std::array<Mapping, {len(simple)}> simple = {{{{",
|
|
]
|
|
lines += [f" {{{char_literal(entry['input'])}, {json.dumps(entry['output'], ensure_ascii=False)}}}," for entry in simple]
|
|
lines += [
|
|
"}};",
|
|
f"inline constexpr std::array<AlternatingMapping, {len(alternating)}> alternating = {{{{",
|
|
]
|
|
lines += [
|
|
f" {{{char_literal(entry['input'])}, {json.dumps(entry['opening'], ensure_ascii=False)}, {json.dumps(entry['closing'], ensure_ascii=False)}}},"
|
|
for entry in alternating
|
|
]
|
|
lines += [
|
|
"}};",
|
|
f"inline constexpr char nested_opening_input = {char_literal(nested['openingInput'])};",
|
|
f"inline constexpr char nested_closing_input = {char_literal(nested['closingInput'])};",
|
|
f"inline constexpr char nested_opening[] = {json.dumps(nested['opening'], ensure_ascii=False)};",
|
|
f"inline constexpr char nested_opening_inner[] = {json.dumps(nested['nestedOpening'], ensure_ascii=False)};",
|
|
f"inline constexpr char nested_closing[] = {json.dumps(nested['closing'], ensure_ascii=False)};",
|
|
f"inline constexpr char nested_closing_inner[] = {json.dumps(nested['nestedClosing'], ensure_ascii=False)};",
|
|
"constexpr bool is_supported(char input)",
|
|
"{",
|
|
" for (const auto &mapping : simple)",
|
|
" if (mapping.input == input) return true;",
|
|
" for (const auto &mapping : alternating)",
|
|
" if (mapping.input == input) return true;",
|
|
" return input == nested_opening_input || input == nested_closing_input;",
|
|
"}",
|
|
"constexpr const char *simple_output(char input)",
|
|
"{",
|
|
" for (const auto &mapping : simple)",
|
|
" if (mapping.input == input) return mapping.output;",
|
|
" return nullptr;",
|
|
"}",
|
|
"constexpr const AlternatingMapping *alternating_mapping(char input)",
|
|
"{",
|
|
" for (const auto &mapping : alternating)",
|
|
" if (mapping.input == input) return &mapping;",
|
|
" return nullptr;",
|
|
"}",
|
|
"} // namespace metasequoia::punctuation_contract",
|
|
"",
|
|
]
|
|
expected = "\n".join(lines)
|
|
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--check", action="store_true")
|
|
args = parser.parse_args()
|
|
target = ROOT / "policy.h"
|
|
if args.check:
|
|
if not target.exists() or target.read_text(encoding="utf-8") != expected:
|
|
raise SystemExit("Punctuation contract header is stale; run contracts/punctuation/generate.py")
|
|
else:
|
|
target.write_text(expected, encoding="utf-8")
|