svharness 0.14.13 → 0.14.17

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 (32) hide show
  1. package/README.md +148 -9
  2. package/assets/codechat-agent.ico +0 -0
  3. package/dist/adapters/codex.js +19 -0
  4. package/dist/adapters/index.js +2 -0
  5. package/dist/commands/doctor/utils.js +2 -0
  6. package/dist/commands/init.js +37 -129
  7. package/dist/commands/shell-integration.js +40 -3
  8. package/dist/commands/wiki.js +127 -0
  9. package/dist/config/index.js +2 -1
  10. package/dist/config/merge-options.js +19 -0
  11. package/dist/config/normalize.js +18 -0
  12. package/dist/core/state.js +39 -0
  13. package/dist/index.js +58 -10
  14. package/dist/lib/agent-launcher.js +14 -16
  15. package/dist/lib/codechat-runner-resolver.js +208 -0
  16. package/dist/lib/wiki/run-wiki-generation.js +161 -0
  17. package/dist/lib/win-registry.js +10 -0
  18. package/dist/utils/validate-args.js +1 -0
  19. package/dist/wiki/repowikiIndexer.js +19 -150
  20. package/dist/wiki/repowikiPrompts.js +296 -0
  21. package/dist/wiki/repowikiStructureNormalize.js +31 -1
  22. package/dist/wiki/wikiTasksWriter.js +59 -22
  23. package/docs/agent-launcher-design.md +127 -26
  24. package/docs/standalone-codechat-ps1.md +123 -0
  25. package/package.json +2 -1
  26. package/scripts/preuninstall.js +45 -5
  27. package/templates/_shared/build-rules/harness-build-rule-agent-agnostic.md +2 -2
  28. package/templates/_shared/build-rules/harness-build-rule-specs-schema.md +1 -1
  29. package/templates/_shared/build-skills/harness-build-skill-orchestrator.md +1 -1
  30. package/templates/_shared/build-skills/harness-build-skill-wiki-writer.md +15 -6
  31. package/templates/codechat/Start-CodeChat.ps1 +359 -0
  32. package/templates/svharness.config.example.yaml +7 -0
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ /**
3
+ * Shared wiki generation logic used by both `svharness build` (Step 6b) and
4
+ * the standalone `svharness wiki` subcommand.
5
+ *
6
+ * This module is harness-agnostic: callers provide absolute paths for the
7
+ * source repo root and output directory. The `build` path copies baseline code
8
+ * first and outputs to `<harness>/baseline/wiki/`; the standalone `wiki` path
9
+ * scans source in-place and outputs to `./wiki/`.
10
+ */
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.runWikiGeneration = runWikiGeneration;
16
+ const fs_extra_1 = __importDefault(require("fs-extra"));
17
+ const node_path_1 = __importDefault(require("node:path"));
18
+ const wiki_1 = require("../../wiki");
19
+ /**
20
+ * Guard that the source directory exists and is non-empty.
21
+ * Throws if the directory is missing or empty.
22
+ */
23
+ async function assertSourceNotEmpty(repoRootFs) {
24
+ const exists = await fs_extra_1.default.pathExists(repoRootFs);
25
+ const entries = exists ? await fs_extra_1.default.readdir(repoRootFs) : [];
26
+ if (!exists || entries.length === 0) {
27
+ throw new Error(`Wiki 源码目录为空或不存在:${repoRootFs}。` +
28
+ '请检查 --wiki-source 路径或基线拷贝结果。');
29
+ }
30
+ }
31
+ /**
32
+ * Generate baseline wiki content.
33
+ *
34
+ * This function is non-fatal: on failure it returns `{ ok: false }` instead of
35
+ * throwing, allowing callers (build) to continue with a warning.
36
+ */
37
+ async function runWikiGeneration(input) {
38
+ const { repoRootFs, wikiOutputRootFs, wikiRelPath, wikiLang, wikiModel, wikiBaseUrl, wikiApiKey, projectName, cliVersion, mode, cwd, forceFull, sourceRootRel, wikiAudience = 'human', onLog, onProgress, } = input;
39
+ const log = onLog ?? (() => { });
40
+ const progressCb = onProgress ??
41
+ ((p) => {
42
+ if (p.total > 0) {
43
+ log(` [${p.done}/${p.total}] ${p.detail}`);
44
+ }
45
+ else {
46
+ log(` ${p.detail}`);
47
+ }
48
+ });
49
+ const langFolder = wikiLang === 'en' ? 'en' : 'zh';
50
+ const langRun = (0, wiki_1.langRunForRepowikiTarget)(langFolder);
51
+ if (mode === 'full') {
52
+ // --- Full generation (runRepowikiIndex) ---
53
+ let fullOk = false;
54
+ try {
55
+ await assertSourceNotEmpty(repoRootFs);
56
+ const cfg = await (0, wiki_1.resolveWikiRunConfig)({
57
+ cwd: cwd ?? process.cwd(),
58
+ apiKey: wikiApiKey,
59
+ baseUrl: wikiBaseUrl,
60
+ model: wikiModel,
61
+ });
62
+ log(` 源码根:${repoRootFs}`);
63
+ log(` 输出到:${node_path_1.default.join(wikiOutputRootFs, wikiRelPath)}`);
64
+ log(` 语言:${langFolder} · 模型:${cfg.model}`);
65
+ await (0, wiki_1.runRepowikiIndex)({
66
+ repoRootFs,
67
+ wikiOutputRootFs,
68
+ wikiRelPath,
69
+ baseUrl: cfg.baseUrl,
70
+ apiKey: cfg.apiKey,
71
+ model: cfg.model,
72
+ languages: [langRun],
73
+ comprehensiveSections: true,
74
+ wikiAudience,
75
+ forceFull: !!forceFull,
76
+ onLog: log,
77
+ onProgress: progressCb,
78
+ });
79
+ fullOk = true;
80
+ }
81
+ catch (err) {
82
+ if ((0, wiki_1.isAbortError)(err)) {
83
+ log('wiki 生成被中断(已写出部分页可从 checkpoint 恢复)');
84
+ }
85
+ else {
86
+ log(`wiki 生成失败:${err.message}`);
87
+ }
88
+ }
89
+ if (fullOk) {
90
+ return { ok: true, mode: 'full', wikiPhase: 'done', wikiSource: undefined };
91
+ }
92
+ return {
93
+ ok: false,
94
+ mode: 'full',
95
+ wikiPhase: 'pending',
96
+ wikiSource: 'cli-full-degraded',
97
+ };
98
+ }
99
+ // --- Tasks-only mode (runRepowikiOutlineOnly + writeWikiTasks) ---
100
+ try {
101
+ await assertSourceNotEmpty(repoRootFs);
102
+ const cfg = await (0, wiki_1.resolveWikiRunConfig)({
103
+ cwd: cwd ?? process.cwd(),
104
+ apiKey: wikiApiKey,
105
+ baseUrl: wikiBaseUrl,
106
+ model: wikiModel,
107
+ });
108
+ log(` 源码根:${repoRootFs}`);
109
+ log(` 输出到:${node_path_1.default.join(wikiOutputRootFs, wikiRelPath)}`);
110
+ log(` 语言:${langFolder} · 模型:${cfg.model}`);
111
+ log(' 模式:仅任务清单(tasks-only)');
112
+ const outline = await (0, wiki_1.runRepowikiOutlineOnly)({
113
+ repoRootFs,
114
+ wikiOutputRootFs,
115
+ wikiRelPath,
116
+ baseUrl: cfg.baseUrl,
117
+ apiKey: cfg.apiKey,
118
+ model: cfg.model,
119
+ languages: [langRun],
120
+ comprehensiveSections: true,
121
+ wikiAudience,
122
+ onLog: log,
123
+ onProgress: progressCb,
124
+ });
125
+ const resolvedSourceRootRel = sourceRootRel ??
126
+ (node_path_1.default.relative(wikiOutputRootFs, repoRootFs).replace(/\\/g, '/') || '.');
127
+ const tasksPath = await (0, wiki_1.writeWikiTasks)({
128
+ outline,
129
+ targetRoot: wikiOutputRootFs,
130
+ wikiRelPath,
131
+ projectName,
132
+ cliVersion,
133
+ model: cfg.model,
134
+ generatedAtIso: new Date().toISOString(),
135
+ sourceRootRel: resolvedSourceRootRel,
136
+ wikiAudience,
137
+ });
138
+ return {
139
+ ok: true,
140
+ mode: 'tasks',
141
+ wikiPhase: 'pending',
142
+ wikiSource: 'cli-tasks',
143
+ tasksPath,
144
+ pageCount: outline.pages.length,
145
+ };
146
+ }
147
+ catch (err) {
148
+ if ((0, wiki_1.isAbortError)(err)) {
149
+ log('wiki 任务清单生成被中断');
150
+ }
151
+ else {
152
+ log(`wiki 任务清单生成失败:${err.message}`);
153
+ }
154
+ return {
155
+ ok: false,
156
+ mode: 'tasks',
157
+ wikiPhase: 'pending',
158
+ wikiSource: 'cli-tasks',
159
+ };
160
+ }
161
+ }
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SHELL_MENU_LABEL = exports.SHELL_MENU_KEY_DIR = exports.SHELL_MENU_KEY_BG = void 0;
4
4
  exports.regSetDefault = regSetDefault;
5
+ exports.regSetString = regSetString;
5
6
  exports.regDeleteKey = regDeleteKey;
6
7
  exports.regKeyExists = regKeyExists;
7
8
  const child_process_1 = require("child_process");
@@ -18,6 +19,15 @@ function regSetDefault(key, value) {
18
19
  windowsHide: true,
19
20
  });
20
21
  }
22
+ /**
23
+ * Set a named REG_SZ value on a registry key.
24
+ */
25
+ function regSetString(key, name, value) {
26
+ (0, child_process_1.execSync)(`"${REG}" add "${key}" /v "${name}" /t REG_SZ /d "${quoteRegData(value)}" /f`, {
27
+ stdio: 'pipe',
28
+ windowsHide: true,
29
+ });
30
+ }
21
31
  /**
22
32
  * Delete a registry key and subkeys.
23
33
  */
@@ -26,6 +26,7 @@ const SUPPORTED_AGENTS = [
26
26
  'cursor',
27
27
  'claude-code',
28
28
  'opencode',
29
+ 'codex',
29
30
  'generic',
30
31
  ];
31
32
  const DEFAULT_BASELINE_MAX_FILE_KB = 1024;
@@ -49,11 +49,12 @@ const repowikiCheckpoint_1 = require("./repowikiCheckpoint");
49
49
  const repowikiGit_1 = require("./repowikiGit");
50
50
  const repowikiConfig_1 = require("./repowikiConfig");
51
51
  const repowikiStructureNav_1 = require("./repowikiStructureNav");
52
- const repowikiStructureNormalize_1 = require("./repowikiStructureNormalize");
52
+ const repowikiPrompts_1 = require("./repowikiPrompts");
53
53
  const repowikiMarkdownPost_1 = require("./repowikiMarkdownPost");
54
54
  const repowikiMetadataContent_1 = require("./repowikiMetadataContent");
55
55
  const repowikiMetadataJson_1 = require("./repowikiMetadataJson");
56
56
  const wikiStructureXml_1 = require("./wikiStructureXml");
57
+ const repowikiStructureNormalize_1 = require("./repowikiStructureNormalize");
57
58
  /** Canonical labels for outline + page generation (structure step uses `label`). */
58
59
  exports.REPOWIKI_LANG_EN = {
59
60
  folder: "en",
@@ -68,6 +69,9 @@ function langRunForRepowikiTarget(target) {
68
69
  }
69
70
  /** When `languages` is omitted, generate Simplified Chinese only. */
70
71
  const DEFAULT_LANGS = [exports.REPOWIKI_LANG_ZH];
72
+ function resolveWikiAudience(audience) {
73
+ return audience ?? "human";
74
+ }
71
75
  /** AbortSignal that never aborts — used as default when caller passes nothing. */
72
76
  const NEVER_ABORT = new AbortController().signal;
73
77
  async function chatCompletionTextForIndex(signal, params) {
@@ -111,134 +115,8 @@ async function pathExists(abs) {
111
115
  return false;
112
116
  }
113
117
  }
114
- function structurePrompt(repoName, treeText, readmeChunk, structureLang, comprehensive) {
115
- const zhOutlineExtra = structureLang.folder === "zh"
116
- ? `
117
-
118
- 【简体中文硬性要求 — 纲要步骤】凡是给人看的文字(仓库级 <title>/ <description>、每个 <section> 的 <title>、每个 <page> 的 <title> 与 <description>)必须全部是简体中文(zh-CN)。禁止使用英文句子或段落;仅路径、文件名、代码标识符/API 符号可保留英文。`
119
- : "";
120
- const enOutlineExtra = structureLang.folder === "en"
121
- ? `
122
-
123
- 【English hard requirement — outline step】All human-readable text in this XML (repo-level <title>/<description>, each <section>'s <title>, each <page>'s <title> and <description>) MUST be fluent English. Do not write Chinese, Japanese, or other non-English prose for those fields. Only code identifiers, filenames, paths, API symbols, and unavoidable proper nouns may stay non-English where appropriate.`
124
- : "";
125
- const sectionBlock = comprehensive
126
- ? `Use **multiple** top-level \`<section>\` blocks under \`<sections>\`: **between 2 and 7** (inclusive). **Never** return only **one** section when the wiki has **two or more** pages — split topics into **distinct** sections (do **not** collapse everything into a single bucket named after the wiki title).
127
- Use **at most 7** sections total. For very small repos with only **one** page, **one** section is acceptable.
128
- Each section MUST have a **unique** \`id\` attribute (letters, digits, hyphens only — stable identifier).
129
- Each section's \`<title>\` MUST be **in the outline language** (${structureLang.label}), **repo-specific**, and suitable as a section heading (this becomes the subdirectory name under each language folder).
130
- **Filesystem folders** under the language directory are derived from each section \`<title>\` (slugified), **not** from \`id\`.
131
- Distribute pages across sections: each section's \`<pages>\` lists \`<page_ref>\` ids; use **at most ${wikiStructureXml_1.REPOWIKI_MAX_PAGES}** pages **total** across all sections.
132
-
133
- Return ONLY valid XML in this shape:
134
-
135
- <wiki_structure>
136
- <title>[Overall title]</title>
137
- <description>[Brief]</description>
138
- <sections>
139
- <section id="getting-started">
140
- <title>[Section title in outline language]</title>
141
- <pages>
142
- <page_ref>page-1</page_ref>
143
- </pages>
144
- <subsections/>
145
- </section>
146
- <!-- more sections with unique ids -->
147
- </sections>
148
- <pages>
149
- <page id="page-1">
150
- <title>[Title]</title>
151
- <description>[What this covers]</description>
152
- <importance>high</importance>
153
- <relevant_files>
154
- <file_path>[repo-relative/path]</file_path>
155
- </relevant_files>
156
- <related_pages/>
157
- <parent_section>getting-started</parent_section>
158
- </page>
159
- </pages>
160
- </wiki_structure>`
161
- : `<wiki_structure>
162
- <title>[Overall title]</title>
163
- <description>[Brief]</description>
164
- <pages>
165
- <page id="page-1">
166
- <title>[Title]</title>
167
- <description>[What]</description>
168
- <importance>high</importance>
169
- <relevant_files>
170
- <file_path>[path]</file_path>
171
- </relevant_files>
172
- <related_pages/>
173
- </page>
174
- </pages>
175
- </wiki_structure>`;
176
- return `Analyze the repository "${repoName}" and propose a concise developer wiki outline.
177
-
178
- <file_tree>
179
- ${treeText}
180
- </file_tree>
181
-
182
- <readme_excerpt>
183
- ${readmeChunk.slice(0, 12_000)}
184
- </readme_excerpt>
185
-
186
- Target language for human-readable titles/descriptions ONLY in this outline step: ${structureLang.label}.${zhOutlineExtra}${enOutlineExtra}
187
-
188
- ${sectionBlock}
189
-
190
- Rules:
191
- - Produce **at most ${wikiStructureXml_1.REPOWIKI_MAX_PAGES}** wiki pages total with **stable** ids \`page-1\`, \`page-2\`, …, \`page-${wikiStructureXml_1.REPOWIKI_MAX_PAGES}\` (use consecutive ids; fewer pages is OK).
192
- ${comprehensive ? `- Every \`<page>\` MUST include \`<parent_section>\` with the **exact** \`id\` of the section that owns this page (the section whose \`<page_ref>\` lists this page id).\n- Each page id must appear in exactly one section's \`page_ref\` list.` : `- Without a \`<sections>\` block, every page is stored under **one** folder derived from the wiki \`<title>\`; omit \`<parent_section>\` or ignore it for paths.`}
193
- ${comprehensive ? `- Each section \`<title>\` becomes a subdirectory name (slugified); keep titles concise and filesystem-friendly where possible.` : `- The wiki \`<title>\` alone determines that single subdirectory name (slugified).`}
194
- - Ensure \`relevant_files\` cite real paths from file_tree where possible (skip generated/vendor dirs).
195
- ${comprehensive ? `- CRITICAL: Every tag must be closed. After \`<sections>\`, you MUST include one final \`<pages>...</pages>\` block containing every full \`<page id="...">...</page>\` with title, description, parent_section, and relevant_files. Section-level \`<pages>\` may only list \`<page_ref>\` — never omit the outer \`<page>\` definitions.` : `- CRITICAL: Every tag must be closed. Include a \`<pages>\` block listing every full \`<page id="...">...</page>\` with title, description, and relevant_files.`}
196
- - Return ONLY XML. No markdown fences. No HTML. Start with <wiki_structure> end </wiki_structure>.`;
197
- }
198
- function pageMarkdownPrompt(langFolder, langDescriptor, pageTopic, ctx) {
199
- const zhExtra = langFolder === "zh"
200
- ? `
201
-
202
- 【简体中文硬性要求 — 正文】全部正文、各级标题(# / ## / ###)、表格单元格、Mermaid 与其它图中的说明文字一律使用简体中文(zh-CN)。禁止英文句子,除非直接引用代码、路径、标识符或 API 名称。`
203
- : "";
204
- const enExtra = langFolder === "en"
205
- ? `
206
-
207
- 【English hard requirement — body】All prose, headings (# / ## / ###), table cell text, and explanatory labels inside Mermaid/diagrams MUST be English. Do not write Chinese prose (or mixed-language explanations) unless you are quoting literal content from repo files/strings. Preserve non-English only in fenced code excerpts, paths, identifiers, and API symbols as they appear in the repo.`
208
- : "";
209
- const h1Rule = langFolder === "zh"
210
- ? `2. Start with '# [title]' (the H1 must match the topic; for a zh-CN wiki, use Simplified Chinese for that title line).`
211
- : langFolder === "en"
212
- ? `2. Start with '# [title]' (the H1 must match the topic in English prose).`
213
- : `2. Start with '# [title]' (the H1 must match the topic).`;
214
- return `You write accurate technical Markdown documentation for developers.
215
-
216
- Output language: ${langDescriptor}.${zhExtra}${enExtra}
217
-
218
- Repository context bundled as tagged files:
219
-
220
- ${ctx}
221
-
222
- Write ONE wiki page for topic: "${pageTopic}".
223
-
224
- Strict rules:
225
- 1. Ground claims only in supplied files.
226
- ${h1Rule}
227
- 3. After the introduction (first paragraph or short opener) and **before** the first \`##\`, add a concise **table of contents**: a bullet or numbered list of links to the \`##\` sections that follow (use markdown links with anchors, e.g. \`[Section](#section-slug)\`, matching your real headings). **Omit this TOC** if the page is very short or only has a single \`##\` section (avoid a redundant mini-TOC).
228
- 4. Use '##','###', tables, fenced code from files when helpful.
229
- 5. Prefer Mermaid with \`\`\`mermaid diagrams using TOP-DOWN flow (\`graph TD\`, not LR).
230
- 6. Where useful cite repository files on one line: \`Sources: path/to/file:line-range\` (comma-separated if multiple). Paths are repo-relative with \`/\` separators.
231
-
232
- If bundled files lack coverage, acknowledge gaps briefly — do not invent APIs.`;
233
- }
234
- function pageGenerationSystemPrompt(langFolder) {
235
- if (langFolder === "zh") {
236
- return "你是技术文档撰写者,只根据提供的 <file path=…> 摘录作答。Wiki 页的各级标题、正文、表格文字、图中的文字说明必须全部是简体中文(zh-CN)。除代码摘录、仓库路径与标识符/API 英文名外禁止使用英文 prose。";
237
- }
238
- if (langFolder === "en") {
239
- return "You are a technical writer. Answer ONLY from bundled <file path=…> excerpts. The entire Markdown page MUST be English: headings, body, table text, diagram labels/explanations. Use non-English prose only inside literal code fences or when verbatim-quoting user-facing strings from the repository; identifiers, paths, and API symbols follow the codebase.";
240
- }
241
- return "You write factual Markdown grounded strictly in bundled <file path=…> excerpts.";
118
+ async function mkdirp(p) {
119
+ await fs.mkdir(p, { recursive: true });
242
120
  }
243
121
  function normalizeLeadingH1(md, canonicalTitle) {
244
122
  const t = canonicalTitle.trim();
@@ -255,9 +133,6 @@ function normalizeLeadingH1(md, canonicalTitle) {
255
133
  }
256
134
  return md;
257
135
  }
258
- async function mkdirp(p) {
259
- await fs.mkdir(p, { recursive: true });
260
- }
261
136
  function bucketAndStemFromRel(relPosix) {
262
137
  const n = relPosix.replace(/\\/g, "/");
263
138
  const slash = n.lastIndexOf("/");
@@ -314,6 +189,7 @@ async function runRepowikiIndex(opts) {
314
189
  const readme = await (0, repowikiScanner_1.tryReadFirstReadme)(opts.repoRootFs);
315
190
  const structureLang = langs[0] ?? exports.REPOWIKI_LANG_ZH;
316
191
  const langFolders = langs.map((l) => l.folder);
192
+ const wikiAudience = resolveWikiAudience(opts.wikiAudience);
317
193
  let existingCp = forceFull ? null : await (0, repowikiCheckpoint_1.readRepowikiCheckpoint)(wikiBase);
318
194
  if (forceFull && existingCp) {
319
195
  await (0, repowikiCheckpoint_1.clearRepowikiCheckpoint)(wikiBase);
@@ -364,11 +240,7 @@ async function runRepowikiIndex(opts) {
364
240
  if (!resumed) {
365
241
  report?.({ done: 0, total: 0, detail: "Requesting wiki outline from model…" });
366
242
  log("[repowiki] Requesting wiki structure…");
367
- const structureSystem = structureLang.folder === "zh"
368
- ? "你只输出格式正确的 wiki_structure XML(符合用户给定模板);不要使用 markdown 代码围栏。纲要中凡是给人阅读的标题与描述必须使用简体中文(zh-CN)。"
369
- : structureLang.folder === "en"
370
- ? "You output ONLY well-formed wiki_structure XML matching the user's template. Never use markdown fences. Every repo title, wiki title/description, section titles, page titles, and page descriptions meant for humans must be fluent English (no Chinese prose in those strings unless it is unavoidable quoted content from the repository)."
371
- : "You output ONLY well-formed wiki_structure XML matching the user's template. Never use markdown fences.";
243
+ const structureSystem = (0, repowikiPrompts_1.structureSystemPrompt)(wikiAudience, structureLang.folder);
372
244
  const comprehensive = opts.comprehensiveSections ?? false;
373
245
  let structureRaw = await chatCompletionTextForIndex(signal, {
374
246
  baseUrl: opts.baseUrl,
@@ -379,7 +251,7 @@ async function runRepowikiIndex(opts) {
379
251
  { role: "system", content: structureSystem },
380
252
  {
381
253
  role: "user",
382
- content: structurePrompt(repoName, treeText, readme, structureLang, comprehensive),
254
+ content: (0, repowikiPrompts_1.structurePrompt)(wikiAudience, repoName, treeText, readme, structureLang, comprehensive),
383
255
  },
384
256
  ],
385
257
  });
@@ -407,8 +279,8 @@ async function runRepowikiIndex(opts) {
407
279
  { role: "system", content: structureSystem },
408
280
  {
409
281
  role: "user",
410
- content: structurePrompt(repoName, treeText, readme, structureLang, comprehensive) +
411
- (0, repowikiStructureNormalize_1.structureRepairUserAppendix)(structureRaw, structureLang.folder),
282
+ content: (0, repowikiPrompts_1.structurePrompt)(wikiAudience, repoName, treeText, readme, structureLang, comprehensive) +
283
+ (0, repowikiStructureNormalize_1.structureRepairUserAppendix)(structureRaw, structureLang.folder, wikiAudience),
412
284
  },
413
285
  ],
414
286
  });
@@ -586,10 +458,10 @@ async function runRepowikiIndex(opts) {
586
458
  model: opts.model,
587
459
  temperature: 0.25,
588
460
  messages: [
589
- { role: "system", content: pageGenerationSystemPrompt(lg.folder) },
461
+ { role: "system", content: (0, repowikiPrompts_1.pageGenerationSystemPrompt)(wikiAudience, lg.folder) },
590
462
  {
591
463
  role: "user",
592
- content: pageMarkdownPrompt(lg.folder, lg.label, `${page.title}\n\n${page.description}`, ctxBundle),
464
+ content: (0, repowikiPrompts_1.pageMarkdownPrompt)(wikiAudience, lg.folder, lg.label, `${page.title}\n\n${page.description}`, ctxBundle),
593
465
  },
594
466
  ],
595
467
  });
@@ -706,13 +578,10 @@ async function runRepowikiOutlineOnly(opts) {
706
578
  const treeText = (0, repowikiScanner_1.summarizeTreeLines)(fileList, 260);
707
579
  const readme = await (0, repowikiScanner_1.tryReadFirstReadme)(opts.repoRootFs);
708
580
  const structureLang = langs[0] ?? exports.REPOWIKI_LANG_ZH;
581
+ const wikiAudience = resolveWikiAudience(opts.wikiAudience);
709
582
  report?.({ done: 0, total: 0, detail: "Requesting wiki outline from model…" });
710
583
  log("[repowiki] Requesting wiki structure…");
711
- const structureSystem = structureLang.folder === "zh"
712
- ? "你只输出格式正确的 wiki_structure XML(符合用户给定模板);不要使用 markdown 代码围栏。纲要中凡是给人阅读的标题与描述必须使用简体中文(zh-CN)。"
713
- : structureLang.folder === "en"
714
- ? "You output ONLY well-formed wiki_structure XML matching the user's template. Never use markdown fences. Every repo title, wiki title/description, section titles, page titles, and page descriptions meant for humans must be fluent English (no Chinese prose in those strings unless it is unavoidable quoted content from the repository)."
715
- : "You output ONLY well-formed wiki_structure XML matching the user's template. Never use markdown fences.";
584
+ const structureSystem = (0, repowikiPrompts_1.structureSystemPrompt)(wikiAudience, structureLang.folder);
716
585
  const comprehensive = opts.comprehensiveSections ?? false;
717
586
  let structureRaw = await chatCompletionTextForIndex(signal, {
718
587
  baseUrl: opts.baseUrl,
@@ -723,7 +592,7 @@ async function runRepowikiOutlineOnly(opts) {
723
592
  { role: "system", content: structureSystem },
724
593
  {
725
594
  role: "user",
726
- content: structurePrompt(repoName, treeText, readme, structureLang, comprehensive),
595
+ content: (0, repowikiPrompts_1.structurePrompt)(wikiAudience, repoName, treeText, readme, structureLang, comprehensive),
727
596
  },
728
597
  ],
729
598
  });
@@ -751,8 +620,8 @@ async function runRepowikiOutlineOnly(opts) {
751
620
  { role: "system", content: structureSystem },
752
621
  {
753
622
  role: "user",
754
- content: structurePrompt(repoName, treeText, readme, structureLang, comprehensive) +
755
- (0, repowikiStructureNormalize_1.structureRepairUserAppendix)(structureRaw, structureLang.folder),
623
+ content: (0, repowikiPrompts_1.structurePrompt)(wikiAudience, repoName, treeText, readme, structureLang, comprehensive) +
624
+ (0, repowikiStructureNormalize_1.structureRepairUserAppendix)(structureRaw, structureLang.folder, wikiAudience),
756
625
  },
757
626
  ],
758
627
  });