@coralai/sps-cli 0.56.2 → 0.56.3

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.
Files changed (82) hide show
  1. package/dist/console/routes/chat.d.ts +8 -0
  2. package/dist/console/routes/chat.d.ts.map +1 -1
  3. package/dist/console/routes/chat.js +157 -30
  4. package/dist/console/routes/chat.js.map +1 -1
  5. package/dist/main.js +0 -0
  6. package/dist/services/ChatService.d.ts +10 -0
  7. package/dist/services/ChatService.d.ts.map +1 -1
  8. package/dist/services/ChatService.js +9 -1
  9. package/dist/services/ChatService.js.map +1 -1
  10. package/package.json +1 -1
  11. package/dist/commands/wikiCommand.d.ts +0 -77
  12. package/dist/commands/wikiCommand.d.ts.map +0 -1
  13. package/dist/commands/wikiCommand.js +0 -489
  14. package/dist/commands/wikiCommand.js.map +0 -1
  15. package/dist/core/skillStore.d.ts +0 -55
  16. package/dist/core/skillStore.d.ts.map +0 -1
  17. package/dist/core/skillStore.js +0 -224
  18. package/dist/core/skillStore.js.map +0 -1
  19. package/dist/core/wiki/frontmatter.d.ts +0 -55
  20. package/dist/core/wiki/frontmatter.d.ts.map +0 -1
  21. package/dist/core/wiki/frontmatter.js +0 -109
  22. package/dist/core/wiki/frontmatter.js.map +0 -1
  23. package/dist/core/wiki/hot.d.ts +0 -27
  24. package/dist/core/wiki/hot.d.ts.map +0 -1
  25. package/dist/core/wiki/hot.js +0 -124
  26. package/dist/core/wiki/hot.js.map +0 -1
  27. package/dist/core/wiki/index-builder.d.ts +0 -37
  28. package/dist/core/wiki/index-builder.d.ts.map +0 -1
  29. package/dist/core/wiki/index-builder.js +0 -130
  30. package/dist/core/wiki/index-builder.js.map +0 -1
  31. package/dist/core/wiki/linter.d.ts +0 -76
  32. package/dist/core/wiki/linter.d.ts.map +0 -1
  33. package/dist/core/wiki/linter.js +0 -280
  34. package/dist/core/wiki/linter.js.map +0 -1
  35. package/dist/core/wiki/log.d.ts +0 -24
  36. package/dist/core/wiki/log.d.ts.map +0 -1
  37. package/dist/core/wiki/log.js +0 -107
  38. package/dist/core/wiki/log.js.map +0 -1
  39. package/dist/core/wiki/manifest.d.ts +0 -59
  40. package/dist/core/wiki/manifest.d.ts.map +0 -1
  41. package/dist/core/wiki/manifest.js +0 -180
  42. package/dist/core/wiki/manifest.js.map +0 -1
  43. package/dist/core/wiki/page.d.ts +0 -72
  44. package/dist/core/wiki/page.d.ts.map +0 -1
  45. package/dist/core/wiki/page.js +0 -221
  46. package/dist/core/wiki/page.js.map +0 -1
  47. package/dist/core/wiki/reader.d.ts +0 -102
  48. package/dist/core/wiki/reader.d.ts.map +0 -1
  49. package/dist/core/wiki/reader.js +0 -225
  50. package/dist/core/wiki/reader.js.map +0 -1
  51. package/dist/core/wiki/scaffold.d.ts +0 -42
  52. package/dist/core/wiki/scaffold.d.ts.map +0 -1
  53. package/dist/core/wiki/scaffold.js +0 -223
  54. package/dist/core/wiki/scaffold.js.map +0 -1
  55. package/dist/core/wiki/searcher.d.ts +0 -73
  56. package/dist/core/wiki/searcher.d.ts.map +0 -1
  57. package/dist/core/wiki/searcher.js +0 -216
  58. package/dist/core/wiki/searcher.js.map +0 -1
  59. package/dist/core/wiki/sources.d.ts +0 -84
  60. package/dist/core/wiki/sources.d.ts.map +0 -1
  61. package/dist/core/wiki/sources.js +0 -261
  62. package/dist/core/wiki/sources.js.map +0 -1
  63. package/dist/core/wiki/types.d.ts +0 -441
  64. package/dist/core/wiki/types.d.ts.map +0 -1
  65. package/dist/core/wiki/types.js +0 -109
  66. package/dist/core/wiki/types.js.map +0 -1
  67. package/dist/shared/wikiPaths.d.ts +0 -38
  68. package/dist/shared/wikiPaths.d.ts.map +0 -1
  69. package/dist/shared/wikiPaths.js +0 -89
  70. package/dist/shared/wikiPaths.js.map +0 -1
  71. package/project-template/.claude/CLAUDE.md +0 -66
  72. package/project-template/.claude/hooks/start.sh +0 -44
  73. package/project-template/.claude/hooks/stop.sh +0 -54
  74. package/project-template/.claude/rules/.gitkeep +0 -0
  75. package/project-template/.claude/settings.json +0 -32
  76. package/project-template/.claude/settings.local.json.template +0 -3
  77. package/project-template/.claude/skills/.gitkeep +0 -0
  78. package/project-template/README.md +0 -10
  79. package/project-template/batch_scheduler.sh +0 -8
  80. package/project-template/conf.template +0 -61
  81. package/project-template/deploy.sh +0 -3
  82. package/project-template/pm_meta/.gitkeep +0 -0
@@ -1,224 +0,0 @@
1
- /**
2
- * @module skillStore
3
- * @description Skill 分发核心:user-level ~/.coral/skills/ ↔ project-level .claude/skills/
4
- *
5
- * @role core
6
- * @layer core
7
- * @boundedContext skill-distribution
8
- *
9
- * @responsibilities
10
- * - 列举 user-level skills(~/.coral/skills/)
11
- * - 在项目中 add/remove/freeze/unfreeze skill
12
- * - 默认用 symlink(同机器稳定路径),失败回退 cpSync
13
- * - 区分 linked(symlink)/ frozen(真实副本)/ foreign(未知目录)
14
- */
15
- import { appendFileSync, cpSync, existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, readlinkSync, rmSync, statSync, symlinkSync, } from 'node:fs';
16
- import { resolve } from 'node:path';
17
- const HOME = process.env.HOME || '/home/coral';
18
- // 新模型:技能单一源 = 全局 ~/.claude/skills(CoralSkills setup.sh 软链进去);不再用 ~/.coral/skills 注册表。
19
- const USER_SKILLS_DIR = resolve(HOME, '.claude', 'skills');
20
- export function userSkillsRoot() {
21
- return USER_SKILLS_DIR;
22
- }
23
- export function listUserSkills() {
24
- if (!existsSync(USER_SKILLS_DIR))
25
- return [];
26
- return readdirSync(USER_SKILLS_DIR, { withFileTypes: true })
27
- .filter((e) => {
28
- // 普通目录或指向目录的 symlink 都算(外部 skill 包经常用 symlink 接入)
29
- if (e.isDirectory())
30
- return true;
31
- if (!e.isSymbolicLink())
32
- return false;
33
- try {
34
- // statSync 跟随 symlink,解析到目标
35
- return statSync(resolve(USER_SKILLS_DIR, e.name)).isDirectory();
36
- }
37
- catch {
38
- return false;
39
- }
40
- })
41
- .map((e) => ({
42
- name: e.name,
43
- userPath: resolve(USER_SKILLS_DIR, e.name),
44
- hasSkillMd: existsSync(resolve(USER_SKILLS_DIR, e.name, 'SKILL.md')),
45
- }))
46
- .filter((s) => s.hasSkillMd);
47
- }
48
- export function projectSkillsDir(projectDir) {
49
- return resolve(projectDir, '.claude', 'skills');
50
- }
51
- export function projectSkillPath(projectDir, name) {
52
- return resolve(projectSkillsDir(projectDir), name);
53
- }
54
- export function inspectProjectSkill(projectDir, name) {
55
- const user = listUserSkills().find((s) => s.name === name);
56
- if (!user)
57
- return null;
58
- const p = projectSkillPath(projectDir, name);
59
- if (!existsSync(p))
60
- return { ...user, state: 'absent' };
61
- const stat = lstatSync(p);
62
- if (stat.isSymbolicLink()) {
63
- let target;
64
- try {
65
- target = readlinkSync(p);
66
- }
67
- catch {
68
- /* ignore */
69
- }
70
- return { ...user, state: 'linked', target };
71
- }
72
- return { ...user, state: 'frozen' };
73
- }
74
- export function addSkillToProject(projectDir, name) {
75
- const user = listUserSkills().find((s) => s.name === name);
76
- if (!user)
77
- return 'skipped-absent';
78
- const skillsDir = projectSkillsDir(projectDir);
79
- if (!existsSync(skillsDir))
80
- mkdirSync(skillsDir, { recursive: true });
81
- const dst = projectSkillPath(projectDir, name);
82
- if (existsSync(dst)) {
83
- return lstatSync(dst).isSymbolicLink() ? 'skipped-linked' : 'skipped-frozen';
84
- }
85
- try {
86
- symlinkSync(user.userPath, dst, 'dir');
87
- return 'linked';
88
- }
89
- catch {
90
- cpSync(user.userPath, dst, { recursive: true, force: false });
91
- return 'copied';
92
- }
93
- }
94
- export function removeSkillFromProject(projectDir, name) {
95
- const p = projectSkillPath(projectDir, name);
96
- if (!existsSync(p) && !isDanglingSymlink(p))
97
- return false;
98
- rmSync(p, { recursive: true, force: true });
99
- return true;
100
- }
101
- export function freezeSkillInProject(projectDir, name) {
102
- const p = projectSkillPath(projectDir, name);
103
- if (!existsSync(p))
104
- return false;
105
- const stat = lstatSync(p);
106
- if (!stat.isSymbolicLink())
107
- return false;
108
- const user = listUserSkills().find((s) => s.name === name);
109
- if (!user)
110
- return false;
111
- rmSync(p);
112
- cpSync(user.userPath, p, { recursive: true, force: true });
113
- return true;
114
- }
115
- export function unfreezeSkillInProject(projectDir, name) {
116
- const p = projectSkillPath(projectDir, name);
117
- const user = listUserSkills().find((s) => s.name === name);
118
- if (!user)
119
- return false;
120
- if (existsSync(p)) {
121
- const stat = lstatSync(p);
122
- if (stat.isSymbolicLink())
123
- return false;
124
- rmSync(p, { recursive: true, force: true });
125
- }
126
- const skillsDir = projectSkillsDir(projectDir);
127
- if (!existsSync(skillsDir))
128
- mkdirSync(skillsDir, { recursive: true });
129
- symlinkSync(user.userPath, p, 'dir');
130
- return true;
131
- }
132
- /**
133
- * Bulk link every user-level skill into the project. Idempotent:
134
- * - absent → symlink(或回退 cpSync)
135
- * - linked → 保留
136
- * - frozen → 保留(用户已 freeze 的不重建)
137
- */
138
- export function syncAllSkillsToProject(projectDir) {
139
- const users = listUserSkills();
140
- let linked = 0;
141
- let copied = 0;
142
- let kept = 0;
143
- for (const u of users) {
144
- const r = addSkillToProject(projectDir, u.name);
145
- if (r === 'linked')
146
- linked++;
147
- else if (r === 'copied')
148
- copied++;
149
- else
150
- kept++;
151
- }
152
- return { linked, copied, kept };
153
- }
154
- /**
155
- * 把 bundled skills(npm 包内 skills/)拷贝到 ~/.coral/skills/。
156
- *
157
- * 默认 non-destructive:已存在的 skill 目录保留,不覆盖用户改动。
158
- * `force=true`(v0.51.2+):用 bundled 的 SKILL.md 覆盖(升级 sps-cli 后拉新 SOP)。
159
- * 注意:force 会覆盖用户对 ~/.coral/skills/<name>/ 的直接编辑。如想保留定制,
160
- * 先 `sps skill freeze <name> --project <p>` 把它固化到项目级(项目级副本不受
161
- * sync 影响)。
162
- *
163
- * Bundled → user 必须是 cpSync,因为 npm 包路径会随重装变化,symlink 会失效。
164
- */
165
- export function syncBundledSkillsToUser(bundledSkillsDir, opts = {}) {
166
- if (!existsSync(bundledSkillsDir))
167
- return { copied: 0, updated: 0, skipped: 0 };
168
- if (!existsSync(USER_SKILLS_DIR))
169
- mkdirSync(USER_SKILLS_DIR, { recursive: true });
170
- let copied = 0;
171
- let updated = 0;
172
- let skipped = 0;
173
- const entries = readdirSync(bundledSkillsDir, { withFileTypes: true });
174
- for (const entry of entries) {
175
- if (!entry.isDirectory())
176
- continue;
177
- const src = resolve(bundledSkillsDir, entry.name);
178
- if (!existsSync(resolve(src, 'SKILL.md')))
179
- continue;
180
- const dst = resolve(USER_SKILLS_DIR, entry.name);
181
- if (existsSync(dst)) {
182
- if (opts.force) {
183
- cpSync(src, dst, { recursive: true, force: true });
184
- updated++;
185
- }
186
- else {
187
- skipped++;
188
- }
189
- continue;
190
- }
191
- cpSync(src, dst, { recursive: true, force: false });
192
- copied++;
193
- }
194
- return { copied, updated, skipped };
195
- }
196
- /**
197
- * 把 .claude/skills/ 条目追加到 .gitignore(幂等)。
198
- * 项目级 skill 是 symlink 到本机 ~/.coral/,不该进仓库。
199
- */
200
- export function ensureSkillsGitignore(projectDir) {
201
- const gitignore = resolve(projectDir, '.gitignore');
202
- const entry = '.claude/skills/';
203
- let existing = '';
204
- if (existsSync(gitignore))
205
- existing = readFileSync(gitignore, 'utf-8');
206
- const has = existing
207
- .split('\n')
208
- .map((l) => l.trim())
209
- .some((l) => l === entry || l === '.claude/skills');
210
- if (has)
211
- return;
212
- const prefix = existing && !existing.endsWith('\n') ? '\n' : '';
213
- appendFileSync(gitignore, `${prefix}${entry}\n`);
214
- }
215
- function isDanglingSymlink(p) {
216
- try {
217
- const stat = lstatSync(p);
218
- return stat.isSymbolicLink();
219
- }
220
- catch {
221
- return false;
222
- }
223
- }
224
- //# sourceMappingURL=skillStore.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"skillStore.js","sourceRoot":"","sources":["../../src/core/skillStore.ts"],"names":[],"mappings":"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"}
@@ -1,55 +0,0 @@
1
- import { type Frontmatter } from './types.js';
2
- export interface ParseResult {
3
- readonly frontmatter: Frontmatter;
4
- readonly body: string;
5
- }
6
- export declare class FrontmatterError extends Error {
7
- readonly cause?: unknown | undefined;
8
- readonly issues?: readonly {
9
- path: string;
10
- message: string;
11
- }[] | undefined;
12
- constructor(message: string, cause?: unknown | undefined, issues?: readonly {
13
- path: string;
14
- message: string;
15
- }[] | undefined);
16
- }
17
- /**
18
- * 从完整 markdown 文件内容解析 frontmatter + body。
19
- * 严格模式:
20
- * - 没 `---\n...\n---\n` 块 → throw
21
- * - YAML 解析失败 → throw
22
- * - zod 校验失败 → throw(issues 字段带详细路径)
23
- */
24
- export declare function parseFrontmatter(content: string): ParseResult;
25
- /**
26
- * 宽松解析:失败时返 null + 错误,不抛。
27
- * 用途:lint 扫描整个 wiki 时,单页坏不该终止整个 lint。
28
- */
29
- export declare function tryParseFrontmatter(content: string): {
30
- ok: true;
31
- value: ParseResult;
32
- } | {
33
- ok: false;
34
- error: FrontmatterError;
35
- };
36
- /**
37
- * Frontmatter + body → 完整 markdown 文件内容。
38
- *
39
- * - YAML 输出走 yaml lib 默认行为(块式、整齐排版、字符串可选引号)
40
- * - body 末尾保证一个换行(POSIX 文件尾约定)
41
- * - 校验过 frontmatter 才能进来——这里不再校验,调用方传合法对象
42
- */
43
- export declare function serializeFrontmatter(frontmatter: Frontmatter, body: string): string;
44
- /**
45
- * 校验 frontmatter 对象(不需要先序列化)。
46
- * 用于:内存里组装 page 后写盘前快速检查。
47
- */
48
- export declare function validateFrontmatter(fm: unknown): {
49
- ok: true;
50
- value: Frontmatter;
51
- } | {
52
- ok: false;
53
- error: FrontmatterError;
54
- };
55
- //# sourceMappingURL=frontmatter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../../src/core/wiki/frontmatter.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,KAAK,WAAW,EAAqB,MAAM,YAAY,CAAC;AAMjE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,gBAAiB,SAAQ,KAAK;IAGvC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE;gBAF9D,OAAO,EAAE,MAAM,EACN,KAAK,CAAC,EAAE,OAAO,YAAA,EACf,MAAM,CAAC,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,YAAA;CAKjE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAiC7D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,GACd;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,gBAAgB,CAAA;CAAE,CAS3E;AAID;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAWnF;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,OAAO,GACV;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,gBAAgB,CAAA;CAAE,CAW3E"}
@@ -1,109 +0,0 @@
1
- /**
2
- * @module core/wiki/frontmatter
3
- * @description Frontmatter 解析、序列化、校验
4
- *
5
- * @layer core
6
- *
7
- * 输入:raw markdown 文件内容(开头是 YAML 块 + body)。
8
- * 输出:分离的 frontmatter(zod 校验过)+ body。
9
- *
10
- * 关键约束:
11
- * - 扁平 YAML(doc-28 §6 Page Schema)—— Obsidian Properties UI 不支持嵌套
12
- * - 缺 frontmatter / 不合法 → 返 error,**不 silently 接受残缺**
13
- * wiki page 来自 LLM 写入,松散 schema 会让格式漂移失控
14
- */
15
- import YAML from 'yaml';
16
- import { FrontmatterSchema } from './types.js';
17
- // ─── 解析 ─────────────────────────────────────────────────────────
18
- const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
19
- export class FrontmatterError extends Error {
20
- cause;
21
- issues;
22
- constructor(message, cause, issues) {
23
- super(message);
24
- this.cause = cause;
25
- this.issues = issues;
26
- this.name = 'FrontmatterError';
27
- }
28
- }
29
- /**
30
- * 从完整 markdown 文件内容解析 frontmatter + body。
31
- * 严格模式:
32
- * - 没 `---\n...\n---\n` 块 → throw
33
- * - YAML 解析失败 → throw
34
- * - zod 校验失败 → throw(issues 字段带详细路径)
35
- */
36
- export function parseFrontmatter(content) {
37
- const match = content.match(FRONTMATTER_RE);
38
- if (!match) {
39
- throw new FrontmatterError('No frontmatter block found. Page must start with `---\\n<yaml>\\n---\\n`.');
40
- }
41
- const yamlBlock = match[1] ?? '';
42
- const body = (match[2] ?? '').replace(/^\n+/, '');
43
- let parsed;
44
- try {
45
- parsed = YAML.parse(yamlBlock);
46
- }
47
- catch (err) {
48
- throw new FrontmatterError('YAML parse error in frontmatter', err);
49
- }
50
- if (parsed === null || typeof parsed !== 'object') {
51
- throw new FrontmatterError('Frontmatter must be a YAML object');
52
- }
53
- const result = FrontmatterSchema.safeParse(parsed);
54
- if (!result.success) {
55
- throw new FrontmatterError('Frontmatter schema validation failed', result.error, result.error.issues.map((i) => ({
56
- path: i.path.join('.'),
57
- message: i.message,
58
- })));
59
- }
60
- return { frontmatter: result.data, body };
61
- }
62
- /**
63
- * 宽松解析:失败时返 null + 错误,不抛。
64
- * 用途:lint 扫描整个 wiki 时,单页坏不该终止整个 lint。
65
- */
66
- export function tryParseFrontmatter(content) {
67
- try {
68
- return { ok: true, value: parseFrontmatter(content) };
69
- }
70
- catch (err) {
71
- return {
72
- ok: false,
73
- error: err instanceof FrontmatterError ? err : new FrontmatterError(String(err), err),
74
- };
75
- }
76
- }
77
- // ─── 序列化 ───────────────────────────────────────────────────────
78
- /**
79
- * Frontmatter + body → 完整 markdown 文件内容。
80
- *
81
- * - YAML 输出走 yaml lib 默认行为(块式、整齐排版、字符串可选引号)
82
- * - body 末尾保证一个换行(POSIX 文件尾约定)
83
- * - 校验过 frontmatter 才能进来——这里不再校验,调用方传合法对象
84
- */
85
- export function serializeFrontmatter(frontmatter, body) {
86
- // 用 yaml lib 控制输出风格
87
- const yamlText = YAML.stringify(frontmatter, {
88
- indent: 2,
89
- lineWidth: 0, // 不自动折行(避免 wikilink 被切到下一行)
90
- defaultStringType: 'PLAIN',
91
- defaultKeyType: 'PLAIN',
92
- }).replace(/\n$/, ''); // YAML.stringify 末尾会带 \n,去掉留我们自己控
93
- const bodyTrimmed = body.replace(/^\n+/, '').replace(/\n+$/, '');
94
- return `---\n${yamlText}\n---\n\n${bodyTrimmed}\n`;
95
- }
96
- /**
97
- * 校验 frontmatter 对象(不需要先序列化)。
98
- * 用于:内存里组装 page 后写盘前快速检查。
99
- */
100
- export function validateFrontmatter(fm) {
101
- const result = FrontmatterSchema.safeParse(fm);
102
- if (result.success)
103
- return { ok: true, value: result.data };
104
- return {
105
- ok: false,
106
- error: new FrontmatterError('Frontmatter validation failed', result.error, result.error.issues.map((i) => ({ path: i.path.join('.'), message: i.message }))),
107
- };
108
- }
109
- //# sourceMappingURL=frontmatter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../../../src/core/wiki/frontmatter.ts"],"names":[],"mappings":"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"}
@@ -1,27 +0,0 @@
1
- /**
2
- * 读 hot.md。文件不存在或损坏 → 返默认骨架(不阻塞 Worker prompt 注入)。
3
- */
4
- export declare function readHot(repoDir: string): string;
5
- export interface HotCacheUpdate {
6
- /** 时间戳(ISO 8601);缺省 = now */
7
- updatedAt?: string;
8
- /** Last Updated 段的描述(一句话:"完成卡 #18,加了 race-recovery") */
9
- lastUpdate: string;
10
- /** Key Recent Facts 列表(每条一行) */
11
- keyFacts?: readonly string[];
12
- /** Recent Changes 列表(每条一行,建议带 [[wikilink]]) */
13
- recentChanges?: readonly string[];
14
- /** Active Threads 列表 */
15
- activeThreads?: readonly string[];
16
- }
17
- /**
18
- * 用结构化数据生成 hot.md 完整内容(覆盖式更新——hot 是 cache,不是 journal)。
19
- *
20
- * 长度控制:超过 SOFT_LIMIT 在末尾加 truncation 提示;超过 HARD_LIMIT 截断。
21
- */
22
- export declare function renderHot(update: HotCacheUpdate): string;
23
- /**
24
- * 渲染 + 原子写入 hot.md。
25
- */
26
- export declare function writeHot(repoDir: string, update: HotCacheUpdate): void;
27
- //# sourceMappingURL=hot.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hot.d.ts","sourceRoot":"","sources":["../../../src/core/wiki/hot.ts"],"names":[],"mappings":"AA+CA;;GAEG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAS/C;AAID,MAAM,WAAW,cAAc;IAC7B,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,UAAU,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,+CAA+C;IAC/C,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,wBAAwB;IACxB,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CA+CxD;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAMtE"}
@@ -1,124 +0,0 @@
1
- /**
2
- * @module core/wiki/hot
3
- * @description Wiki hot.md 缓存:~500 字最近上下文(per-instance,gitignored)
4
- *
5
- * @layer core
6
- *
7
- * doc-28 §10 / claude-obsidian "hot cache" 机制:每次 ingest / 卡完成后更新
8
- * 一份"最近发生了什么"摘要,下次 Worker 启动瞬间 prime。
9
- *
10
- * 实现要点:
11
- * - 文件位置:`<repo>/wiki/.hot.md`(gitignored,per-instance 飘移)
12
- * - 长度软上限 500 字(hard cap 1000 字截断)
13
- * - 不存在 → 返默认骨架(让 Worker 不会因缺文件就出错)
14
- * - 写入时校验 frontmatter 是 valid meta page
15
- */
16
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
17
- import { dirname } from 'node:path';
18
- import { wikiHotFile } from '../../shared/wikiPaths.js';
19
- // ─── Defaults ─────────────────────────────────────────────────────
20
- const DEFAULT_HOT_TEMPLATE = `---
21
- type: meta
22
- title: Hot Cache
23
- updated: 1970-01-01T00:00:00Z
24
- ---
25
-
26
- # Recent Context
27
-
28
- ## Last Updated
29
- (尚无活动。第一次 \`sps wiki update\` 或卡片完成后会自动填充。)
30
-
31
- ## Key Recent Facts
32
- (none yet)
33
-
34
- ## Recent Changes
35
- (none yet)
36
-
37
- ## Active Threads
38
- (none yet)
39
- `;
40
- const SOFT_LIMIT_CHARS = 4000; // ~500 中文字 / ~1000 英文字
41
- const HARD_LIMIT_CHARS = 8000;
42
- // ─── Read ─────────────────────────────────────────────────────────
43
- /**
44
- * 读 hot.md。文件不存在或损坏 → 返默认骨架(不阻塞 Worker prompt 注入)。
45
- */
46
- export function readHot(repoDir) {
47
- const path = wikiHotFile(repoDir);
48
- if (!existsSync(path))
49
- return DEFAULT_HOT_TEMPLATE;
50
- try {
51
- const content = readFileSync(path, 'utf-8');
52
- return content;
53
- }
54
- catch {
55
- return DEFAULT_HOT_TEMPLATE;
56
- }
57
- }
58
- /**
59
- * 用结构化数据生成 hot.md 完整内容(覆盖式更新——hot 是 cache,不是 journal)。
60
- *
61
- * 长度控制:超过 SOFT_LIMIT 在末尾加 truncation 提示;超过 HARD_LIMIT 截断。
62
- */
63
- export function renderHot(update) {
64
- const ts = update.updatedAt ?? new Date().toISOString();
65
- const lines = [
66
- '---',
67
- 'type: meta',
68
- 'title: Hot Cache',
69
- `updated: ${ts}`,
70
- '---',
71
- '',
72
- '# Recent Context',
73
- '',
74
- '## Last Updated',
75
- update.lastUpdate.trim(),
76
- '',
77
- '## Key Recent Facts',
78
- ];
79
- if (update.keyFacts && update.keyFacts.length > 0) {
80
- for (const f of update.keyFacts)
81
- lines.push(`- ${f}`);
82
- }
83
- else {
84
- lines.push('(none)');
85
- }
86
- lines.push('', '## Recent Changes');
87
- if (update.recentChanges && update.recentChanges.length > 0) {
88
- for (const c of update.recentChanges)
89
- lines.push(`- ${c}`);
90
- }
91
- else {
92
- lines.push('(none)');
93
- }
94
- lines.push('', '## Active Threads');
95
- if (update.activeThreads && update.activeThreads.length > 0) {
96
- for (const t of update.activeThreads)
97
- lines.push(`- ${t}`);
98
- }
99
- else {
100
- lines.push('(none)');
101
- }
102
- let content = lines.join('\n') + '\n';
103
- if (content.length > SOFT_LIMIT_CHARS) {
104
- if (content.length > HARD_LIMIT_CHARS) {
105
- content = content.slice(0, HARD_LIMIT_CHARS) + '\n…(truncated to hard cap; review hot.md and trim)\n';
106
- }
107
- else {
108
- content += '\n> ⚠ Hot cache exceeds soft limit (~500 字). Trim if needed.\n';
109
- }
110
- }
111
- return content;
112
- }
113
- /**
114
- * 渲染 + 原子写入 hot.md。
115
- */
116
- export function writeHot(repoDir, update) {
117
- const path = wikiHotFile(repoDir);
118
- const dir = dirname(path);
119
- if (!existsSync(dir))
120
- mkdirSync(dir, { recursive: true });
121
- const content = renderHot(update);
122
- writeFileSync(path, content, { encoding: 'utf-8', mode: 0o644 });
123
- }
124
- //# sourceMappingURL=hot.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hot.js","sourceRoot":"","sources":["../../../src/core/wiki/hot.ts"],"names":[],"mappings":"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"}
@@ -1,37 +0,0 @@
1
- import type { Page } from './types.js';
2
- /**
3
- * 从 page 列表渲染 index.md 完整内容。
4
- *
5
- * 输出形如:
6
- * ```md
7
- * ---
8
- * type: meta
9
- * title: Wiki Index
10
- * updated: 2026-04-27
11
- * ---
12
- *
13
- * # Wiki Index
14
- *
15
- * Pages: 12 · Updated 2026-04-27
16
- *
17
- * ## Modules (3)
18
- * - [[modules/PipelineService]]: TL;DR 摘要短句...
19
- * - ...
20
- *
21
- * ## Lessons (4)
22
- * - [[lessons/Stop Hook Race]]: ...
23
- * ```
24
- */
25
- export declare function renderIndex(pages: readonly Page[], opts?: {
26
- updatedAt?: string;
27
- }): string;
28
- /**
29
- * 写 index.md(全量重建)。
30
- */
31
- export declare function writeIndex(repoDir: string, pages: readonly Page[]): void;
32
- /**
33
- * 取 index.md 节选 top-N 行(不含 frontmatter)。
34
- * 给 reader.ts 的 Layer 2 用——总是注入这一段。
35
- */
36
- export declare function readIndexSummary(repoDir: string, maxLines?: number): string;
37
- //# sourceMappingURL=index-builder.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-builder.d.ts","sourceRoot":"","sources":["../../../src/core/wiki/index-builder.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,IAAI,EAAY,MAAM,YAAY,CAAC;AAYjD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,EAAE,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,MAAM,CAuC7F;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,IAAI,EAAE,GAAG,IAAI,CAMxE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,SAAK,GAAG,MAAM,CAgBvE"}