orosus 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,3 @@
1
- import { JsonlSessionStore, SqliteSessionStore, appendInput, atomicWriteTextSync, checkTrust, createHarness, defaultEventIndexFile, deriveMessages, discoverModules, encodeCwd, hardeningNote, isEmptySessionHead, loadConfig, loadSecretsEnv, loadTrustStore, locateSessionFile, lookupModelsDevContextWindow, modelsDevCacheFile, normalizeTrustKey, purgeSessionDir, readInputs, readSessionHead, refreshEventIndex, repairFile, resolveContextWindow, saveTrustStore, scanBucketSessions, scanSessionFiles, sectionPath, sqliteAvailable, sweepEmptySessions, trustModule, verifyChain, writeNestedTable, writeSectionKey } from "./src-BgvcCPOY.js";
1
+ import { JsonlSessionStore, SqliteSessionStore, appendInput, atomicWriteTextSync, checkTrust, createHarness, defaultEventIndexFile, deriveMessages, discoverModules, encodeCwd, hardeningNote, isEmptySessionHead, loadConfig, loadSecretsEnv, loadTrustStore, locateSessionFile, lookupModelsDevContextWindow, modelsDevCacheFile, normalizeTrustKey, purgeSessionDir, readInputs, readSessionHead, refreshEventIndex, repairFile, resolveContextWindow, saveTrustStore, scanBucketSessions, scanSessionFiles, sectionPath, sqliteAvailable, sweepEmptySessions, trustModule, verifyChain, writeNestedTable, writeSectionKey } from "./src-Cr2EWEaI.js";
2
2
 
3
3
  export { JsonlSessionStore };
@@ -1667,15 +1667,15 @@ async function openSessionView(opts) {
1667
1667
  function verifyChain(events, opts) {
1668
1668
  const issues = [];
1669
1669
  const segments = [];
1670
- let current = [];
1670
+ let current$1 = [];
1671
1671
  for (const e of events) {
1672
- if (e.parentId === null && e.type === "session/header" && current.length > 0) {
1673
- segments.push(current);
1674
- current = [];
1672
+ if (e.parentId === null && e.type === "session/header" && current$1.length > 0) {
1673
+ segments.push(current$1);
1674
+ current$1 = [];
1675
1675
  }
1676
- current.push(e);
1676
+ current$1.push(e);
1677
1677
  }
1678
- if (current.length > 0) segments.push(current);
1678
+ if (current$1.length > 0) segments.push(current$1);
1679
1679
  for (const seg of segments) {
1680
1680
  let junctionLeft = opts?.windowedHead === true;
1681
1681
  for (let i = 1; i < seg.length; i++) {
@@ -2367,10 +2367,10 @@ function createEventBus(sink) {
2367
2367
  return void 0;
2368
2368
  },
2369
2369
  async reduce(type, value) {
2370
- let current = value;
2370
+ let current$1 = value;
2371
2371
  for (const e of chain(type)) try {
2372
- const r = await e.listener(current);
2373
- if (r !== void 0) current = r;
2372
+ const r = await e.listener(current$1);
2373
+ if (r !== void 0) current$1 = r;
2374
2374
  } catch (err) {
2375
2375
  log.error("kernel.bus.reduce-error", `reduce 环抛错被忽略`, {
2376
2376
  type,
@@ -2378,7 +2378,7 @@ function createEventBus(sink) {
2378
2378
  error: String(err)
2379
2379
  });
2380
2380
  }
2381
- return current;
2381
+ return current$1;
2382
2382
  },
2383
2383
  async collect(type) {
2384
2384
  const out = [];
@@ -2828,8 +2828,12 @@ const PUBLIC_CAPABILITY_KEYS = [
2828
2828
  "fs",
2829
2829
  "shell",
2830
2830
  "mcp",
2831
- "skill"
2831
+ "skill",
2832
+ "i18n.locale",
2833
+ "i18n.catalog"
2832
2834
  ];
2835
+ /** 前缀形公共能力(m5-i18n T2 命名登记):i18n.locale.*(语言包,每语言单所有者)/ i18n.catalog.*(模块目录,每模块单所有者)。 */
2836
+ const PUBLIC_CAPABILITY_PREFIXES = ["i18n.locale.", "i18n.catalog."];
2833
2837
  /** 核心保留槽(§7.2):走 provide 注册、不计入 provides 声明。 */
2834
2838
  const CORE_RESERVED_SLOT_PREFIXES = ["provider:"];
2835
2839
  const CORE_RESERVED_SLOT_KEYS = ["auth.apikey", "loop.next-turn"];
@@ -2847,7 +2851,7 @@ function validateModule(def) {
2847
2851
  v.push(`provides 含核心保留槽 key "${key}"(§7.2:保留槽不计入 provides 声明、由 provide 注册)`);
2848
2852
  continue;
2849
2853
  }
2850
- const isPublic = PUBLIC_CAPABILITY_KEYS.includes(key);
2854
+ const isPublic = PUBLIC_CAPABILITY_KEYS.includes(key) || PUBLIC_CAPABILITY_PREFIXES.some((p) => key.startsWith(p));
2851
2855
  const isPrefixed = key.startsWith(`${def.name}.`);
2852
2856
  if (!isPublic && !isPrefixed) v.push(`provides 的 key "${key}" 既非 contracts 登记的公共短名、也未带模块名前缀 "${def.name}."(规则 1)`);
2853
2857
  }
@@ -2976,6 +2980,321 @@ function resolveTopo(input) {
2976
2980
  };
2977
2981
  }
2978
2982
 
2983
+ //#endregion
2984
+ //#region ../../packages/i18n/src/runtime.ts
2985
+ /** 表格转义惯例:单元格里模板管道用全角 | 书写(避免与 Markdown 表列冲突),解析前归一。 */
2986
+ const FULLWIDTH_PIPE = "|";
2987
+ /** 形参名:字母开头,允许 :. - 与 hh:mm:ss 类冒号;可带一节「空格 + 短尾」({reason 首行}——查参取首 token)。 */
2988
+ const PARAM_RE = /^[A-Za-z_][A-Za-z0-9_:.]*(?: [^\s{}]{1,8})?$/;
2989
+ /** 复数形前缀:one/other/few/many 或数字样本形(1:/2:/5:)。 */
2990
+ const CAT_RE = /^(one|other|few|many|\d+)\s*:/;
2991
+ function paramValue(params, name) {
2992
+ if (params === void 0) return void 0;
2993
+ const direct = params[name];
2994
+ if (direct !== void 0) return direct;
2995
+ const head = name.split(" ")[0];
2996
+ return params[head];
2997
+ }
2998
+ function isPresent(v) {
2999
+ return v !== void 0 && v !== null && v !== "" && v !== false;
3000
+ }
3001
+ /** CLDR 复数类(六语够用子集:ru 三形、en 两形、zh/ja/ko 单形)。 */
3002
+ function pluralCategory(tag, n) {
3003
+ if (!Number.isFinite(n)) return "other";
3004
+ const abs = Math.abs(n);
3005
+ const i10 = abs % 10;
3006
+ const i100 = abs % 100;
3007
+ const t = tag.toLowerCase();
3008
+ if (t.startsWith("ru")) {
3009
+ if (i10 === 1 && i100 !== 11) return "one";
3010
+ if (i10 >= 2 && i10 <= 4 && !(i100 >= 12 && i100 <= 14)) return "few";
3011
+ return "many";
3012
+ }
3013
+ if (t.startsWith("en")) return abs === 1 ? "one" : "other";
3014
+ return "other";
3015
+ }
3016
+ /** 首个数值形参(复数选形依据——调用方按序传入计数值)。 */
3017
+ function firstNumeric(params) {
3018
+ if (params === void 0) return Number.NaN;
3019
+ for (const v of Object.values(params)) {
3020
+ if (typeof v === "number") return v;
3021
+ if (typeof v === "string" && v !== "" && /^\d+$/.test(v)) return Number(v);
3022
+ }
3023
+ return Number.NaN;
3024
+ }
3025
+ /** 深度感知的顶层切分(跳过内层 {…} 组;分隔符可为 | 或 /)。 */
3026
+ function splitTop(content, sep$1) {
3027
+ const segs = [];
3028
+ let depth = 0;
3029
+ let cur = "";
3030
+ for (const ch of content) {
3031
+ if (ch === "{") depth++;
3032
+ else if (ch === "}") depth = Math.max(0, depth - 1);
3033
+ if (ch === sep$1 && depth === 0) {
3034
+ segs.push(cur);
3035
+ cur = "";
3036
+ } else cur += ch;
3037
+ }
3038
+ segs.push(cur);
3039
+ return segs;
3040
+ }
3041
+ /** 段内顶层形参名收集(浅层——内层组的形参不属本段判定面)。 */
3042
+ function paramNamesOf(segment) {
3043
+ const names = [];
3044
+ let depth = 0;
3045
+ let cur = "";
3046
+ for (const ch of segment) {
3047
+ if (ch === "{") {
3048
+ depth++;
3049
+ if (depth === 1) cur = "";
3050
+ continue;
3051
+ }
3052
+ if (ch === "}") {
3053
+ depth = Math.max(0, depth - 1);
3054
+ if (depth === 0 && cur !== "" && PARAM_RE.test(cur.split(FULLWIDTH_PIPE).join("|"))) names.push(cur.split(" ")[0].split(FULLWIDTH_PIPE)[0].split("|")[0]);
3055
+ continue;
3056
+ }
3057
+ if (depth >= 1) cur += ch;
3058
+ }
3059
+ return names;
3060
+ }
3061
+ function interpolate(template, params, tag) {
3062
+ let out = "";
3063
+ let i = 0;
3064
+ while (i < template.length) {
3065
+ const ch = template[i];
3066
+ if (ch !== "{") {
3067
+ out += ch;
3068
+ i++;
3069
+ continue;
3070
+ }
3071
+ let depth = 0;
3072
+ let j = i;
3073
+ for (; j < template.length; j++) if (template[j] === "{") depth++;
3074
+ else if (template[j] === "}") {
3075
+ depth--;
3076
+ if (depth === 0) break;
3077
+ }
3078
+ if (j >= template.length) {
3079
+ out += ch;
3080
+ i++;
3081
+ continue;
3082
+ }
3083
+ out += renderChunk(template.slice(i + 1, j), params, tag);
3084
+ i = j + 1;
3085
+ }
3086
+ return out;
3087
+ }
3088
+ function renderChunk(rawChunk, params, tag) {
3089
+ const chunk = rawChunk.split(FULLWIDTH_PIPE).join("|");
3090
+ const cond = /^([A-Za-z_][A-Za-z0-9_:.]*)\?([\s\S]+)$/.exec(chunk);
3091
+ if (cond) return isPresent(paramValue(params, cond[1])) ? interpolate(cond[2], params, tag) : "";
3092
+ if (PARAM_RE.test(chunk)) {
3093
+ const v = paramValue(params, chunk);
3094
+ return isPresent(v) ? String(v) : "";
3095
+ }
3096
+ const pipeSegs = splitTop(chunk, "|");
3097
+ if (pipeSegs.length > 1) {
3098
+ if (PARAM_RE.test(pipeSegs[0])) {
3099
+ const v = paramValue(params, pipeSegs[0]);
3100
+ return isPresent(v) ? String(v) : interpolate(pipeSegs.slice(1).join("|"), params, tag);
3101
+ }
3102
+ if (pipeSegs.every((s) => CAT_RE.test(s.trim()))) return selectVariant(pipeSegs, params, tag);
3103
+ return pickAlternative(pipeSegs, params, tag);
3104
+ }
3105
+ const slashSegs = splitTop(chunk, "/");
3106
+ if (slashSegs.length > 1) {
3107
+ if (slashSegs.every((s) => CAT_RE.test(s.trim()))) return selectVariant(slashSegs, params, tag);
3108
+ if (PARAM_RE.test(slashSegs[0].trim())) {
3109
+ const v = paramValue(params, slashSegs[0].trim());
3110
+ return isPresent(v) ? String(v) : interpolate(slashSegs.slice(1).join("/"), params, tag);
3111
+ }
3112
+ return pickAlternative(slashSegs, params, tag);
3113
+ }
3114
+ const inner = paramNamesOf(chunk);
3115
+ if (inner.length > 0) {
3116
+ const allPresent = inner.every((n) => isPresent(paramValue(params, n)));
3117
+ return allPresent ? interpolate(chunk, params, tag) : "";
3118
+ }
3119
+ return `{${rawChunk}}`;
3120
+ }
3121
+ function selectVariant(segs, params, tag) {
3122
+ const variants = new Map();
3123
+ for (const seg of segs) {
3124
+ const m = CAT_RE.exec(seg.trim());
3125
+ if (m) variants.set(m[1], seg.trim().slice(m[0].length));
3126
+ }
3127
+ const n = firstNumeric(params);
3128
+ const cat = pluralCategory(tag, n);
3129
+ const exemplar = {
3130
+ one: "1",
3131
+ few: "2",
3132
+ many: "5"
3133
+ };
3134
+ const picked = variants.get(cat) ?? (exemplar[cat] !== void 0 ? variants.get(exemplar[cat]) : void 0) ?? variants.values().next().value ?? "";
3135
+ return interpolate(picked, params, tag);
3136
+ }
3137
+ function pickAlternative(segs, params, tag) {
3138
+ const analyzed = segs.map((s) => {
3139
+ const names = paramNamesOf(s);
3140
+ return {
3141
+ seg: s,
3142
+ names,
3143
+ missing: names.filter((n) => !isPresent(paramValue(params, n)))
3144
+ };
3145
+ });
3146
+ for (let k = analyzed.length - 1; k >= 0; k--) {
3147
+ const a = analyzed[k];
3148
+ if (a.names.length > 0 && a.missing.length === 0) return interpolate(a.seg, params, tag);
3149
+ }
3150
+ for (const a of analyzed) if (a.names.length === 0) return interpolate(a.seg, params, tag);
3151
+ return interpolate(analyzed[0].seg, params, tag);
3152
+ }
3153
+ /** 单条模板格式化(公开面——宿主 store 与预算测试直接用)。 */
3154
+ function formatTemplate(template, params, tag = "en-US") {
3155
+ return interpolate(template, params, tag);
3156
+ }
3157
+ /** 解析链:zh-TW 特例经 zh-CN;其余 active → en-US(去重)。 */
3158
+ function chainFor(tag) {
3159
+ if (tag === "zh-TW") return [
3160
+ "zh-TW",
3161
+ "zh-CN",
3162
+ "en-US"
3163
+ ];
3164
+ if (tag === "en-US") return ["en-US"];
3165
+ return [tag, "en-US"];
3166
+ }
3167
+ /** 链上逐表找键;命中返回 { tag, value }(tag 供复数选形用)。 */
3168
+ function resolveMessage(chain, getTable, key) {
3169
+ for (const tag of chain) {
3170
+ const table = getTable(tag);
3171
+ const value = table?.[key];
3172
+ if (value !== void 0) return {
3173
+ tag,
3174
+ value
3175
+ };
3176
+ }
3177
+ return void 0;
3178
+ }
3179
+ /** 语言标签归一(P3 分族):剥 codeset/修饰后缀(zh_TW.big5 → zh-TW);zh 裸码与 Hans 系 → zh-CN;
3180
+ * Hant 系 → zh-TW;en* → en-US;六语包裸码补全(ja→ja-JP / ko→ko-KR / ru→ru-RU);
3181
+ * 其余区域大写规范化后原样透传。 */
3182
+ function normalizeLocaleTag(raw) {
3183
+ const t = (raw ?? "").trim().replace(/_/g, "-").toLowerCase().replace(/[.@].*$/, "");
3184
+ if (t === "") return "en-US";
3185
+ if (t === "zh" || t.startsWith("zh-hans") || t === "zh-cn" || t === "zh-sg" || t === "zh-my") return "zh-CN";
3186
+ if (t.startsWith("zh-hant") || t === "zh-tw" || t === "zh-hk" || t === "zh-mo" || t === "zh-hant-tw") return "zh-TW";
3187
+ if (t === "en" || t.startsWith("en-")) return "en-US";
3188
+ if (t === "ja") return "ja-JP";
3189
+ if (t === "ko") return "ko-KR";
3190
+ if (t === "ru") return "ru-RU";
3191
+ const parts = t.split("-");
3192
+ if (parts.length === 2) return `${parts[0]}-${parts[1].toUpperCase()}`;
3193
+ return t;
3194
+ }
3195
+ function createT(init) {
3196
+ let tag = init.tag;
3197
+ const t = (key, params, fallback) => {
3198
+ const hit = resolveMessage(chainFor(tag), init.getTable, key);
3199
+ if (hit === void 0) return fallback !== void 0 ? fallback : key;
3200
+ return formatTemplate(hit.value, params, hit.tag);
3201
+ };
3202
+ t.setTag = (next) => {
3203
+ tag = next;
3204
+ };
3205
+ t.getTag = () => tag;
3206
+ return t;
3207
+ }
3208
+
3209
+ //#endregion
3210
+ //#region ../../packages/i18n/src/floor.ts
3211
+ const floorZhCN = {
3212
+ "core.activate.err.cascade": "硬依赖能力 \"{key}\" 的提供者 {name} 已降级(级联降级)",
3213
+ "core.activate.err.noProvide": "硬依赖能力 \"{key}\" 未注册:其提供者已激活但未 provide(提供者模块 bug)",
3214
+ "core.activate.err.config": "配置校验失败:{error}",
3215
+ "core.kernel.err.dupName": "模块名冲突(全局唯一,§5.1)",
3216
+ "core.kernel.disabled": "未启用(defaultEnabled=false 或配置/CLI 禁用,§5.4)",
3217
+ "core.kernel.err.unknown": "未知(failReason 缺省兜底)",
3218
+ "core.loader.err.notObject": "非模块制品:default 导出不是对象(期待 defineModule 的返回值)",
3219
+ "core.loader.err.notModule": "非模块制品:缺 name 或 activate(不是 defineModule 形状,§8.4)",
3220
+ "core.model.ask.fallback": "model(端点清单拉取失败:{err}——输入全名,或回车用默认 {model|未设})",
3221
+ "core.effort.menu.title": "选择思考档位({bare}{ · 当前 {cur}})",
3222
+ "core.help.builtin.header": "内建命令:",
3223
+ "core.help.alias.header": "别名命令:",
3224
+ "core.help.alias.row": "/{short} → {full}{(未安装对应模块)}",
3225
+ "core.help.module.header": "模块命令:",
3226
+ "core.help.module.empty": "(无)",
3227
+ "core.reload.summary": "reload 完成:added {list|无} / removed {list|无} / reloaded {list|无} / unchanged {n} / failed{:{name}({reason 首行})…| 无}",
3228
+ "core.context.model": "模型: {model|(未配置)}",
3229
+ "core.context.rest": "窗口: {n} tokens{({pct}%)} / 未知(/provider import --model 可写入) / 已用: ~{n} tokens({pct}%)"
3230
+ };
3231
+ const floorZhTW = {
3232
+ "core.activate.err.cascade": "硬依賴能力 \"{key}\" 的提供者 {name} 已降級(級聯降級)",
3233
+ "core.activate.err.noProvide": "硬依賴能力 \"{key}\" 未註冊:其提供者已啟用但未 provide(提供者模組 bug)",
3234
+ "core.activate.err.config": "設定校驗失敗:{error}",
3235
+ "core.kernel.err.dupName": "模組名稱衝突(全域唯一,§5.1)",
3236
+ "core.kernel.disabled": "未啟用(defaultEnabled=false 或設定/CLI 停用,§5.4)",
3237
+ "core.kernel.err.unknown": "未知(failReason 缺省兜底)",
3238
+ "core.loader.err.notObject": "非模組製品:default 匯出不是物件(期待 defineModule 的回傳值)",
3239
+ "core.loader.err.notModule": "非模組製品:缺 name 或 activate(不是 defineModule 形狀,§8.4)",
3240
+ "core.model.ask.fallback": "model(端點清單拉取失敗:{err}——輸入全名,或按 Enter 用預設 {model|未設})",
3241
+ "core.effort.menu.title": "選擇思考檔位({bare}{ · 目前 {cur}})",
3242
+ "core.help.builtin.header": "內建命令:",
3243
+ "core.help.alias.header": "別名命令:",
3244
+ "core.help.alias.row": "/{short} → {full}{(未安裝對應模組)}",
3245
+ "core.help.module.header": "模組命令:",
3246
+ "core.help.module.empty": "(無)",
3247
+ "core.reload.summary": "reload 完成:added {list|無} / removed {list|無} / reloaded {list|無} / unchanged {n} / failed{:{name}({reason 首行})…| 無}",
3248
+ "core.context.model": "模型: {model|(未配置)}",
3249
+ "core.context.rest": "視窗: {n} tokens{({pct}%)} / 未知(/provider import --model 可寫入) / 已用: ~{n} tokens({pct}%)"
3250
+ };
3251
+ const floorEnUS = {
3252
+ "core.activate.err.cascade": "The provider {name} of hard-required capability \"{key}\" is degraded (cascading degradation)",
3253
+ "core.activate.err.noProvide": "Hard-required capability \"{key}\" is not registered: its provider activated but never called provide (provider module bug)",
3254
+ "core.activate.err.config": "Configuration validation failed: {error}",
3255
+ "core.kernel.err.dupName": "Module name clash (globally unique, §5.1)",
3256
+ "core.kernel.disabled": "Not enabled (defaultEnabled=false or disabled via config/CLI, §5.4)",
3257
+ "core.kernel.err.unknown": "Unknown (failReason fallback default)",
3258
+ "core.loader.err.notObject": "Not a module artifact: the default export is not an object (expected the return value of defineModule)",
3259
+ "core.loader.err.notModule": "Not a module artifact: missing name or activate (not a defineModule shape, §8.4)",
3260
+ "core.model.ask.fallback": "model (endpoint catalog fetch failed: {err} — type the full name, or press Enter for the default {model|unset})",
3261
+ "core.effort.menu.title": "Select thinking effort ({bare}{ · current {cur}})",
3262
+ "core.help.builtin.header": "Built-in commands:",
3263
+ "core.help.alias.header": "Alias commands:",
3264
+ "core.help.alias.row": "/{short} → {full}{ (corresponding module not installed)}",
3265
+ "core.help.module.header": "Module commands:",
3266
+ "core.help.module.empty": "(None)",
3267
+ "core.reload.summary": "reload complete: added {list|none} / removed {list|none} / reloaded {list|none} / unchanged {n} / failed{: {name} ({reason 首行})…| none}",
3268
+ "core.context.model": "Model: {model|(not configured)}",
3269
+ "core.context.rest": "Window: {n} tokens{ ({pct}%)} / unknown (/provider import --model can set it) / Used: ~{n} tokens ({pct}%)"
3270
+ };
3271
+ const floorCatalogs = {
3272
+ "zh-CN": floorZhCN,
3273
+ "zh-TW": floorZhTW,
3274
+ "en-US": floorEnUS
3275
+ };
3276
+ /** 地板键集(三语 parity 测试与宿主 store 合并用)。 */
3277
+ const floorKeys = Object.keys(floorZhCN);
3278
+
3279
+ //#endregion
3280
+ //#region ../../packages/i18n/src/index.ts
3281
+ /** 地板 t(core/内核自渲染面专用):只认三语地板目录,缺键 → fallback 参数 → key。 */
3282
+ function createFloorT(tag) {
3283
+ return createT({
3284
+ tag,
3285
+ getTable: (t) => floorCatalogs[t]
3286
+ });
3287
+ }
3288
+
3289
+ //#endregion
3290
+ //#region ../../packages/core/src/kernel/i18n.ts
3291
+ let current = createFloorT("zh-CN");
3292
+ function setKernelLocale(raw) {
3293
+ current = raw === void 0 || raw === "" ? createFloorT("zh-CN") : createFloorT(normalizeLocaleTag(raw));
3294
+ }
3295
+ /** core 内 failReason / 自渲染文案统一出口(键见 packages/i18n/src/floor.ts)。 */
3296
+ const kernelT = (key, params, fallback) => current(key, params, fallback);
3297
+
2979
3298
  //#endregion
2980
3299
  //#region ../../packages/core/src/loop/convert.ts
2981
3300
  /** elision 固定模板(v3 设计空白 4,kimi buildCompactionElisionText 语义、条数口径改投影条目)。
@@ -3198,6 +3517,8 @@ ${summary}`
3198
3517
  //#region ../../packages/core/src/kernel/activate.ts
3199
3518
  const PROMPT_SECTION_LIMIT = 32768;
3200
3519
  const PROMPT_TOTAL_LIMIT = 65536;
3520
+ /** 缺省翻译口 = 内核地板 t(宿主未注入窗口期,模块 t 调用仍有话可说——哑系统保险)。 */
3521
+ const kernelFloorT = { t: (key, params, fallback) => kernelT(key, params, fallback) };
3201
3522
  const unassignedLlm = { stream: () => async function* () {
3202
3523
  yield {
3203
3524
  type: "finish",
@@ -3337,12 +3658,15 @@ async function activateModules(input) {
3337
3658
  const missingKey = (def.dependsOn ?? []).filter((d) => typeof d === "string").find((key) => !committedServices.has(key));
3338
3659
  if (missingKey !== void 0) {
3339
3660
  const failedOwner = records.find((r) => r.state === "failed" && (r.def.provides ?? []).includes(missingKey));
3340
- fail(def, failedOwner !== void 0 ? `硬依赖能力 "${missingKey}" 的提供者 ${failedOwner.name} 已降级(级联降级)` : `硬依赖能力 "${missingKey}" 未注册:其提供者已激活但未 provide(提供者模块 bug)`);
3661
+ fail(def, failedOwner !== void 0 ? kernelT("core.activate.err.cascade", {
3662
+ key: missingKey,
3663
+ name: failedOwner.name
3664
+ }) : kernelT("core.activate.err.noProvide", { key: missingKey }));
3341
3665
  continue;
3342
3666
  }
3343
3667
  const cfg = sectionResolution.configFor(def);
3344
3668
  if (!cfg.ok) {
3345
- fail(def, `配置校验失败:${cfg.error}`);
3669
+ fail(def, kernelT("core.activate.err.config", { error: cfg.error }));
3346
3670
  continue;
3347
3671
  }
3348
3672
  const stage = {
@@ -3381,6 +3705,7 @@ async function activateModules(input) {
3381
3705
  },
3382
3706
  log: mlog,
3383
3707
  ui: ownerTagUi(input.commandUi ?? rejectingUi(), def.name),
3708
+ t: (key, params, fallback) => (input.i18n ?? kernelFloorT).t(key, params, fallback),
3384
3709
  llm: {
3385
3710
  stream: (req) => (input.llm?.impl ?? unassignedLlm).stream(req),
3386
3711
  get listModels() {
@@ -3539,6 +3864,10 @@ async function activateModules(input) {
3539
3864
  if (!allows("settings")) throw new Error(`mounts 校验:settings 未在声明(§5.1)`);
3540
3865
  return input.settings.setTheme(n);
3541
3866
  },
3867
+ setLanguage: (tag) => {
3868
+ if (!allows("settings")) throw new Error(`mounts 校验:settings 未在声明(§5.1)`);
3869
+ return input.settings.setLanguage(tag);
3870
+ },
3542
3871
  applyModulePreset: (p) => {
3543
3872
  if (!allows("settings")) throw new Error(`mounts 校验:settings 未在声明(§5.1)`);
3544
3873
  return input.settings.applyModulePreset(p);
@@ -3664,6 +3993,7 @@ async function activateModules(input) {
3664
3993
  return Promise.resolve(s.impl);
3665
3994
  },
3666
3995
  getOptional: (key) => Promise.resolve(committedServices.get(key)?.impl),
3996
+ keys: (prefix) => [...committedServices.keys()].filter((k) => prefix === void 0 || k.startsWith(prefix)),
3667
3997
  listProviders: () => [...committedServices.keys()].filter((k) => k.startsWith("provider:")).map((k) => {
3668
3998
  const impl = committedServices.get(k).impl;
3669
3999
  return typeof impl === "function" ? { name: k.slice(9) } : {
@@ -3789,7 +4119,7 @@ async function loadModules(input) {
3789
4119
  if ((seen.get(def.name) ?? 0) > 1) {
3790
4120
  if (!staticFailed.some((f) => f.name === def.name)) staticFailed.push({
3791
4121
  name: def.name,
3792
- reason: "模块名冲突(全局唯一,§5.1)"
4122
+ reason: kernelT("core.kernel.err.dupName")
3793
4123
  });
3794
4124
  continue;
3795
4125
  }
@@ -3832,6 +4162,7 @@ async function loadModules(input) {
3832
4162
  ...input.sessionSwitch !== void 0 ? { sessionSwitch: input.sessionSwitch } : {},
3833
4163
  ...input.subagent !== void 0 ? { subagent: input.subagent } : {},
3834
4164
  ...input.llm !== void 0 ? { llm: input.llm } : {},
4165
+ ...input.i18n !== void 0 ? { i18n: input.i18n } : {},
3835
4166
  ...input.preserved !== void 0 ? { preserved: input.preserved } : {},
3836
4167
  ...input.generations !== void 0 ? { generations: input.generations } : {},
3837
4168
  ...input.reuse?.overlays !== void 0 ? { overlays: input.reuse.overlays } : {}
@@ -3841,7 +4172,7 @@ async function loadModules(input) {
3841
4172
  ...degraded,
3842
4173
  ...act.records.filter((r) => r.state === "failed").map((r) => ({
3843
4174
  name: r.name,
3844
- reason: r.failReason ?? "未知"
4175
+ reason: r.failReason ?? kernelT("core.kernel.err.unknown")
3845
4176
  }))
3846
4177
  ];
3847
4178
  const requiredFailed = allFailed.filter((f) => sections.isRequired(f.name));
@@ -3893,7 +4224,7 @@ async function loadModules(input) {
3893
4224
  name,
3894
4225
  source: byName.get(name).source,
3895
4226
  state: "discovered",
3896
- failReason: "未启用(defaultEnabled=false 或配置/CLI 禁用,§5.4)",
4227
+ failReason: kernelT("core.kernel.disabled"),
3897
4228
  generation: 1
3898
4229
  }))
3899
4230
  ];
@@ -4001,9 +4332,9 @@ function getJiti() {
4001
4332
  async function loadExternalModule(root, entry) {
4002
4333
  const mod = await getJiti().import(join(root, entry));
4003
4334
  const def = mod.default ?? mod;
4004
- if (typeof def !== "object" || def === null) throw new Error("非模块制品:default 导出不是对象(期待 defineModule 的返回值)");
4335
+ if (typeof def !== "object" || def === null) throw new Error(kernelT("core.loader.err.notObject"));
4005
4336
  const d = def;
4006
- if (typeof d.name !== "string" || typeof d.activate !== "function") throw new Error("非模块制品:缺 name 或 activate(不是 defineModule 形状,§8.4)");
4337
+ if (typeof d.name !== "string" || typeof d.activate !== "function") throw new Error(kernelT("core.loader.err.notModule"));
4007
4338
  return def;
4008
4339
  }
4009
4340
 
@@ -5868,6 +6199,7 @@ async function createHarness(options = {}) {
5868
6199
  const spillDirUsed = options.spillDir ?? join(sessionsDir, store.sessionId, "spill");
5869
6200
  const mediaDirUsed = options.mediaDir ?? join(sessionsDir, store.sessionId, "media");
5870
6201
  const llmHolder = {};
6202
+ const i18nHolder = { t: (key, params, fallback) => kernelT(key, params, fallback) };
5871
6203
  const sessionForkFn = async (forkOpts) => {
5872
6204
  if (store.ensureFull !== void 0) await store.ensureFull();
5873
6205
  const events = await store.all();
@@ -5939,6 +6271,7 @@ async function createHarness(options = {}) {
5939
6271
  cwd: options.cwd ?? process.cwd(),
5940
6272
  commandUi,
5941
6273
  llm: llmHolder,
6274
+ i18n: i18nHolder,
5942
6275
  sessionForkOut: sessionForkFn,
5943
6276
  treeOut: treeFn,
5944
6277
  subagent: subagentRunner,
@@ -6137,6 +6470,10 @@ async function createHarness(options = {}) {
6137
6470
  config.core.effort = level;
6138
6471
  }
6139
6472
  };
6473
+ const applyLanguageOverride = async (tag) => {
6474
+ upsertTopLevelKey(/^\s*language\s*=/, { line: `language = ${tomlBasicString(tag)}` });
6475
+ setKernelLocale(tag);
6476
+ };
6140
6477
  const COMMAND_ALIASES = {
6141
6478
  provider: "provider-custom__provider",
6142
6479
  permission: "approval__permission",
@@ -6187,7 +6524,7 @@ async function createHarness(options = {}) {
6187
6524
  if (parts === void 0) return "未配置模型——先用 /model 或 /provider 选模型";
6188
6525
  const { slotName, bare } = parts;
6189
6526
  const info = await thinkingInfoOf(slotName, bare);
6190
- const current = await resolveStoredEffort();
6527
+ const current$1 = await resolveStoredEffort();
6191
6528
  const arg = args.trim().toLowerCase();
6192
6529
  if (arg !== "") {
6193
6530
  if (!/^[a-z0-9._-]+$/.test(arg)) return `档位名 "${arg}" 不合法(仅限字母数字与 . _ -)`;
@@ -6199,9 +6536,9 @@ async function createHarness(options = {}) {
6199
6536
  return capable ? `模型 ${bare} 无思考档位信息(目录未声明 effort 档——开关型思考或不支持)——可直敲 /effort <档位> 手动指定` : `平台 ${slotName} 不提供思考档位目录——可直敲 /effort <档位> 手动指定(原样发送)`;
6200
6537
  }
6201
6538
  const segments = segmentsOf(info);
6202
- const items = segments.map((v) => v === current ? `${v} ✓` : v);
6203
- const pick = (await commandUi.choose(`选择思考档位(${bare}${current !== void 0 ? ` · 当前 ${current}` : ""})`, items)).replace(/ ✓$/, "");
6204
- if (pick !== current) applyEffortOverride(pick);
6539
+ const items = segments.map((v) => v === current$1 ? `${v} ✓` : v);
6540
+ const pick = (await commandUi.choose(`选择思考档位(${bare}${current$1 !== void 0 ? ` · 当前 ${current$1}` : ""})`, items)).replace(/ ✓$/, "");
6541
+ if (pick !== current$1) applyEffortOverride(pick);
6205
6542
  return "";
6206
6543
  }],
6207
6544
  ["/help", async () => {
@@ -6229,6 +6566,10 @@ async function createHarness(options = {}) {
6229
6566
  }]
6230
6567
  ]);
6231
6568
  const cfgModelValue = () => config.core.provider ?? config.core.model;
6569
+ const cfgLanguageValue = () => {
6570
+ const v = config.core.language;
6571
+ return typeof v === "string" && v !== "" ? v : void 0;
6572
+ };
6232
6573
  const cfgEffortValue = () => {
6233
6574
  const v = config.core.effort;
6234
6575
  return typeof v === "string" && v !== "" ? v : void 0;
@@ -6289,10 +6630,7 @@ async function createHarness(options = {}) {
6289
6630
  }
6290
6631
  const model = explicitModel ?? adapter.defaultModel;
6291
6632
  if (model === void 0) {
6292
- const listing = graph.records.filter((r) => r.state === "active").map((r) => {
6293
- const a = graph.services.provider(r.name);
6294
- return a?.defaultModel !== void 0 ? `${r.name}(默认 ${a.defaultModel})` : `${r.name}(无默认,需写全名)`;
6295
- }).join("、") || "(无)";
6633
+ const listing = graph.services.listProviders().map((s) => s.defaultModel !== void 0 ? `${s.name}(默认 ${s.defaultModel})` : `${s.name}(无默认,需写全名)`).join("、") || "(无)";
6296
6634
  throw new Error(`provider "${provider}" 未声明 defaultModel——请写全名 "<provider>/<model>"。可用 provider:${listing}`);
6297
6635
  }
6298
6636
  return {
@@ -6605,6 +6943,9 @@ async function createHarness(options = {}) {
6605
6943
  }
6606
6944
  }();
6607
6945
  },
6946
+ setModuleT(t) {
6947
+ i18nHolder.t = t;
6948
+ },
6608
6949
  graph() {
6609
6950
  return graph;
6610
6951
  },
@@ -6659,6 +7000,10 @@ async function createHarness(options = {}) {
6659
7000
  async setModel(qualified) {
6660
7001
  await applyModelOverride(qualified);
6661
7002
  },
7003
+ configuredLanguage: () => cfgLanguageValue(),
7004
+ async setLanguage(tag) {
7005
+ await applyLanguageOverride(tag);
7006
+ },
6662
7007
  setEffort(level) {
6663
7008
  applyEffortOverride(level);
6664
7009
  },
@@ -6801,6 +7146,7 @@ async function createHarness(options = {}) {
6801
7146
  cwd: options.cwd ?? process.cwd(),
6802
7147
  commandUi,
6803
7148
  llm: llmHolder,
7149
+ i18n: i18nHolder,
6804
7150
  ...options.settings !== void 0 ? { settings: options.settings } : {},
6805
7151
  ...options.host !== void 0 ? { host: options.host } : {},
6806
7152
  subagent: subagentRunner,
@@ -7115,4 +7461,4 @@ function writeNestedTable(filePath, tablePath, values) {
7115
7461
  }
7116
7462
 
7117
7463
  //#endregion
7118
- export { Access, JsonlSessionStore, SqliteSessionStore, appendInput, atomicWriteTextSync, checkTrust, createHarness, defaultEventIndexFile, defineModule, defineTool, deriveMessages, discoverModules, encodeCwd, hardeningNote, isEmptySessionHead, loadConfig, loadSecretsEnv, loadTrustStore, locateSessionFile, lookupModelsDevContextWindow, modelsDevCacheFile, normalizeTrustKey, orosusHome, purgeSessionDir, readInputs, readSessionHead, refreshEventIndex, repairFile, resolveContextWindow, saveTrustStore, scanBucketSessions, scanSessionFiles, sectionPath, sqliteAvailable, sweepEmptySessions, trustModule, verifyChain, writeNestedTable, writeSectionKey };
7464
+ export { Access, JsonlSessionStore, SqliteSessionStore, appendInput, atomicWriteTextSync, chainFor, checkTrust, createHarness, createT, defaultEventIndexFile, defineModule, defineTool, deriveMessages, discoverModules, encodeCwd, floorCatalogs, hardeningNote, isEmptySessionHead, loadConfig, loadSecretsEnv, loadTrustStore, locateSessionFile, lookupModelsDevContextWindow, modelsDevCacheFile, normalizeLocaleTag, normalizeTrustKey, orosusHome, purgeSessionDir, readInputs, readSessionHead, refreshEventIndex, repairFile, resolveContextWindow, saveTrustStore, scanBucketSessions, scanSessionFiles, sectionPath, sqliteAvailable, sweepEmptySessions, trustModule, verifyChain, writeNestedTable, writeSectionKey };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orosus",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Orosus — terminal AI coding agent with pluggable modules",
5
5
  "type": "module",
6
6
  "license": "MIT",