@modusensus/dsh-mneme 0.10.1 → 0.12.0
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.
- package/README.md +17 -6
- package/bin/dsh-mneme-choro.mjs +254 -0
- package/docs/CONFIGURATION.md +10 -1
- package/lib/api-standalone.js +17 -21
- package/lib/api.js +414 -12
- package/lib/bootstrap-http.js +105 -0
- package/lib/bootstrap.js +5 -1
- package/lib/choro-command.js +104 -0
- package/lib/client.js +1637 -110
- package/lib/config-keys.js +144 -0
- package/lib/config.js +60 -1
- package/lib/document.js +9 -3
- package/lib/dream/clustering.js +6 -1
- package/lib/index.js +87 -5
- package/lib/inject.js +18 -4
- package/lib/lang.js +82 -0
- package/lib/profile-facts.js +356 -0
- package/lib/quality-filter.js +48 -12
- package/lib/service.js +112 -4
- package/lib/settings.js +13 -1
- package/lib/store.js +978 -27
- package/lib/tools.js +244 -1
- package/lib/user-settings.js +63 -7
- package/lib/wiki/inject.js +164 -0
- package/lib/wiki/partition.js +200 -0
- package/lib/wiki/plan.js +214 -0
- package/lib/wiki/queries.js +360 -0
- package/lib/wiki/render.js +187 -0
- package/lib/wiki/scan.js +371 -0
- package/lib/wiki/t0.js +463 -0
- package/lib/wiki/t1.js +496 -0
- package/lib/write-admission.js +5 -3
- package/package.json +4 -2
- package/scripts/sync-test-badge.mjs +1 -1
- package/scripts/test-count-sync.mjs +9 -5
- package/src/api-standalone.js +17 -21
- package/src/api.js +414 -12
- package/src/bootstrap-http.js +105 -0
- package/src/bootstrap.js +5 -1
- package/src/choro-command.js +104 -0
- package/src/config-keys.js +144 -0
- package/src/config.js +60 -1
- package/src/document.js +9 -3
- package/src/dream/clustering.js +6 -1
- package/src/index.js +87 -5
- package/src/inject.js +18 -4
- package/src/lang.js +82 -0
- package/src/profile-facts.js +356 -0
- package/src/quality-filter.js +48 -12
- package/src/service.js +112 -4
- package/src/settings.js +13 -1
- package/src/store.js +978 -27
- package/src/tools.js +244 -1
- package/src/user-settings.js +63 -7
- package/src/wiki/inject.js +164 -0
- package/src/wiki/partition.js +200 -0
- package/src/wiki/plan.js +214 -0
- package/src/wiki/queries.js +360 -0
- package/src/wiki/render.js +187 -0
- package/src/wiki/scan.js +371 -0
- package/src/wiki/t0.js +463 -0
- package/src/wiki/t1.js +496 -0
- package/src/write-admission.js +5 -3
- package/test/api-routes-gaps.test.js +131 -1
- package/test/api.test.js +9 -1
- package/test/bootstrap.test.js +8 -0
- package/test/choro-command.test.js +218 -0
- package/test/client.test.js +802 -21
- package/test/config-keys-routes.test.js +233 -0
- package/test/config.test.js +79 -0
- package/test/contrast.test.js +14 -7
- package/test/document.test.js +32 -0
- package/test/embedding-cache-f32.test.js +276 -0
- package/test/inject-pin-explicit.test.js +300 -0
- package/test/inject-pin-vector-crowd.test.js +225 -0
- package/test/inject.test.js +51 -0
- package/test/llm-audit.test.js +29 -1
- package/test/persona-settings.test.js +31 -0
- package/test/profile-facts.test.js +492 -0
- package/test/quality-backfill.test.js +290 -0
- package/test/quality-filter.test.js +113 -4
- package/test/service.test.js +1 -1
- package/test/session-gate.test.js +1 -1
- package/test/test-count-sync.test.js +14 -3
- package/test/tool-state-ignore.test.js +65 -0
- package/test/tools-dto-schema-matrix.test.js +23 -2
- package/test/tools.test.js +144 -7
- package/test/wiki-api.test.js +273 -0
- package/test/wiki-inject.test.js +265 -0
- package/test/wiki-partition.test.js +112 -0
- package/test/wiki-plan.test.js +80 -0
- package/test/wiki-queries.test.js +270 -0
- package/test/wiki-scan.test.js +208 -0
- package/test/wiki-store.test.js +190 -0
- package/test/wiki-t0.test.js +380 -0
- package/test/wiki-t1.test.js +235 -0
- package/test/wiki-tools.test.js +176 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// dsh-mneme/src/choro-command.js
|
|
2
|
+
// /choro:仓库地志的只读回执(M3,spec §10)。
|
|
3
|
+
//
|
|
4
|
+
// 与 pipeline-command.js 的区别:那边持有状态(开窗 / 结账),这边**什么都不写**。
|
|
5
|
+
// spec §2 D6 定的是「只手动触发,过期只提示」——重建、富化、切档位全都不在这条
|
|
6
|
+
// 命令里,它只回答三个问题:当前仓库登记过地志吗?基线还一致吗?提纲长什么样?
|
|
7
|
+
import { gitHead } from "./wiki/t0.js";
|
|
8
|
+
import { renderChoroBlock } from "./wiki/inject.js";
|
|
9
|
+
import { STR } from "./lang.js";
|
|
10
|
+
|
|
11
|
+
export const CHORO_COMMAND = "choro";
|
|
12
|
+
|
|
13
|
+
/** 短 sha:回执里只用于人眼比对,给全 40 位纯属噪音。 */
|
|
14
|
+
function shortSha(sha) {
|
|
15
|
+
const text = String(sha ?? "").trim();
|
|
16
|
+
return text.length > 7 ? text.slice(0, 7) : text;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** 生成时间只留日期(与注入块同口径:分钟级精度在这块文本里没有信息量)。 */
|
|
20
|
+
function dateOnly(iso) {
|
|
21
|
+
const m = /^(\d{4}-\d{2}-\d{2})/.exec(String(iso ?? ""));
|
|
22
|
+
return m ? m[1] : String(iso ?? "");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 过期判定:地志落库时的 git 基线 vs 当前 HEAD。
|
|
27
|
+
*
|
|
28
|
+
* **只在这里做**——注入块是每轮都要渲染的热路径,fork 一次 git 在 Windows 上
|
|
29
|
+
* 几十毫秒起步(P29)。这里是用户主动敲的,付得起一次 rev-parse。
|
|
30
|
+
* 三种结局分开报:一致 / 不一致 / 读不到 git——不能把「读不到」说成「没过期」。
|
|
31
|
+
*/
|
|
32
|
+
function staleness(repo) {
|
|
33
|
+
const baseline = String(repo.git_baseline ?? "").trim();
|
|
34
|
+
const head = gitHead(repo.root_path);
|
|
35
|
+
if (!head) return { state: "no-git", baseline, head: null };
|
|
36
|
+
if (baseline && baseline === head) return { state: "fresh", baseline, head };
|
|
37
|
+
return { state: "stale", baseline, head };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* 处理函数。返回 CommandResult 形状 { kind, text }——**只作 UI 回执,不进模型
|
|
42
|
+
* 上下文**(同 pipeline-command.js 的契约注释);要模型看提纲,走开局注入那条路。
|
|
43
|
+
*
|
|
44
|
+
* @param {object} opts.choro createChoroQueries() 的产物
|
|
45
|
+
* @param {object} opts.config 合并后的配置
|
|
46
|
+
* @param {() => string} [opts.language]
|
|
47
|
+
*/
|
|
48
|
+
export function createChoroHandler({ choro, config, language = () => "zh" } = {}) {
|
|
49
|
+
return (invocation) => {
|
|
50
|
+
const lang = language() === "en" ? "en" : "zh";
|
|
51
|
+
const S = STR.choroCommandUsage[lang];
|
|
52
|
+
try {
|
|
53
|
+
// 闸只认 chorographyEnabled,不认注入档位:resolveInjectTier 在轻量档下也返回
|
|
54
|
+
// "off",用它当闸会让 lightMode 的用户敲 /choro 时听到「没开,去设置里打开」
|
|
55
|
+
// ——而设置里明明是开着的(档位只管注入,不管这条命令能不能看提纲)。
|
|
56
|
+
if (!config || config.chorographyEnabled !== true) return { kind: "error", text: S.off };
|
|
57
|
+
const raw = invocation?.agent?.session?.header?.cwd ?? null;
|
|
58
|
+
const cwd = typeof raw === "string" ? raw.trim() : "";
|
|
59
|
+
if (!cwd) return { kind: "error", text: S.noCwd };
|
|
60
|
+
const repo = choro ? choro.repoByCwd(cwd) : null;
|
|
61
|
+
if (!repo) return { kind: "error", text: S.noRepo(cwd) };
|
|
62
|
+
const outline = choro.outline(repo.id);
|
|
63
|
+
if (!outline || outline.modules.length === 0) {
|
|
64
|
+
return { kind: "success", text: S.title(repo.name, 0, dateOnly(repo.updated_at)) + "\n" + S.empty };
|
|
65
|
+
}
|
|
66
|
+
const lines = [S.title(repo.name, outline.modules.length, dateOnly(outline.generatedAt))];
|
|
67
|
+
// 命令里的清单不设 light 的 6 行上限:人主动敲了命令就是要看全表。
|
|
68
|
+
// 但 full 档的字符上限仍由 renderChoroBlock 自己兜——回执是 UI 里一个文本框,
|
|
69
|
+
// 贴爆它同样是失败(上限不在这里判,两处各判一次迟早对不上)。
|
|
70
|
+
const block = renderChoroBlock(outline, "full", lang);
|
|
71
|
+
if (block) lines.push(block.split("\n").slice(1).join("\n"));
|
|
72
|
+
// 截断语要说「还剩几个」,不是「总共几个」:总表格行数减去真列出来的行数才是
|
|
73
|
+
// 读者没看到的量。传总数会让人以为「另有 38 个」而实际只漏了 3 个。
|
|
74
|
+
const listed = block ? block.split("\n").filter((line) => line.startsWith("- ")).length : 0;
|
|
75
|
+
const rest = Math.max(0, outline.modules.length - listed);
|
|
76
|
+
if (rest > 0) lines.push(S.truncated(rest));
|
|
77
|
+
const head = staleness(repo);
|
|
78
|
+
if (head.state === "fresh") lines.push(S.fresh(shortSha(head.head)));
|
|
79
|
+
else if (head.state === "stale") lines.push(S.stale(shortSha(head.baseline), shortSha(head.head)));
|
|
80
|
+
else lines.push(S.noGit);
|
|
81
|
+
lines.push(S.hint);
|
|
82
|
+
return { kind: "success", text: lines.filter(Boolean).join("\n") };
|
|
83
|
+
} catch (error) {
|
|
84
|
+
// 回执层永不抛进宿主(同 pipeline-command.js):把原因写进文本就够了。
|
|
85
|
+
return { kind: "error", text: String(error?.message ?? error) };
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* 注册。返回 disposer 或 null(宿主没有命令注册表时静默返回 null,不抛)。
|
|
92
|
+
* 形状与 registerMoRunCommand 一致——两条内置命令只有「做什么」不同。
|
|
93
|
+
*/
|
|
94
|
+
export function registerChoroCommand({ ctx, choro, config, enabled, language = () => "zh" }) {
|
|
95
|
+
if (enabled !== true) return null;
|
|
96
|
+
if (typeof ctx?.commands?.register !== "function") return null;
|
|
97
|
+
const lang = language() === "en" ? "en" : "zh";
|
|
98
|
+
return ctx.commands.register({
|
|
99
|
+
name: CHORO_COMMAND,
|
|
100
|
+
description: STR.choroCommandDescription[lang],
|
|
101
|
+
input: { hint: STR.choroCommandInputHint[lang] },
|
|
102
|
+
handler: createChoroHandler({ choro, config, language })
|
|
103
|
+
});
|
|
104
|
+
}
|