pi-para 0.6.7 → 0.7.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.
- package/ARCHITECTURE.md +4 -6
- package/CHANGELOG.md +19 -0
- package/CONFIGURATION.md +1 -16
- package/README.md +2 -13
- package/SETUP.md +1 -7
- package/STRUCTURE.md +7 -18
- package/dist/cli-legacy.d.ts +2 -1
- package/dist/cli-legacy.d.ts.map +1 -1
- package/dist/cli-legacy.js +13 -25
- package/dist/cli-legacy.js.map +1 -1
- package/dist/cli.d.ts +2 -24
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +29 -271
- package/dist/cli.js.map +1 -1
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +1 -28
- package/dist/commands.js.map +1 -1
- package/dist/config.d.ts +1 -5
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +0 -5
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -64
- package/dist/index.js.map +1 -1
- package/dist/link-utils.d.ts +1 -1
- package/dist/link-utils.js +1 -1
- package/dist/processor.d.ts +7 -0
- package/dist/processor.d.ts.map +1 -1
- package/dist/processor.js +29 -15
- package/dist/processor.js.map +1 -1
- package/dist/settings.d.ts +0 -3
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +0 -11
- package/dist/settings.js.map +1 -1
- package/dist/tools/edit-read.d.ts +18 -0
- package/dist/tools/edit-read.d.ts.map +1 -0
- package/dist/tools/edit-read.js +161 -0
- package/dist/tools/edit-read.js.map +1 -0
- package/dist/tools/ingest.d.ts +12 -0
- package/dist/tools/ingest.d.ts.map +1 -0
- package/dist/tools/ingest.js +48 -0
- package/dist/tools/ingest.js.map +1 -0
- package/dist/tools/lint.d.ts +10 -0
- package/dist/tools/lint.d.ts.map +1 -0
- package/dist/tools/lint.js +57 -0
- package/dist/tools/lint.js.map +1 -0
- package/dist/tools/migrate.d.ts +6 -0
- package/dist/tools/migrate.d.ts.map +1 -0
- package/dist/tools/migrate.js +36 -0
- package/dist/tools/migrate.js.map +1 -0
- package/dist/tools/move.d.ts +9 -0
- package/dist/tools/move.d.ts.map +1 -0
- package/dist/tools/move.js +61 -0
- package/dist/tools/move.js.map +1 -0
- package/dist/tools/query.d.ts +12 -0
- package/dist/tools/query.d.ts.map +1 -0
- package/dist/tools/query.js +47 -0
- package/dist/tools/query.js.map +1 -0
- package/dist/tools/schemas.d.ts +109 -0
- package/dist/tools/schemas.d.ts.map +1 -0
- package/dist/tools/schemas.js +80 -0
- package/dist/tools/schemas.js.map +1 -0
- package/dist/tools/shared.d.ts +14 -0
- package/dist/tools/shared.d.ts.map +1 -0
- package/dist/tools/shared.js +25 -0
- package/dist/tools/shared.js.map +1 -0
- package/dist/tools/summarize.d.ts +8 -0
- package/dist/tools/summarize.d.ts.map +1 -0
- package/dist/tools/summarize.js +82 -0
- package/dist/tools/summarize.js.map +1 -0
- package/dist/tools/write.d.ts +23 -0
- package/dist/tools/write.d.ts.map +1 -0
- package/dist/tools/write.js +215 -0
- package/dist/tools/write.js.map +1 -0
- package/dist/tools.d.ts +1 -8
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +13 -795
- package/dist/tools.js.map +1 -1
- package/dist/wiki.d.ts.map +1 -1
- package/dist/wiki.js +1 -0
- package/dist/wiki.js.map +1 -1
- package/package.json +2 -6
- package/src/cli-legacy.ts +14 -26
- package/src/cli.ts +29 -293
- package/src/commands.ts +0 -21
- package/src/config.ts +1 -6
- package/src/index.ts +5 -66
- package/src/link-utils.ts +1 -1
- package/src/processor.ts +28 -13
- package/src/settings.ts +0 -14
- package/src/tools/edit-read.ts +193 -0
- package/src/tools/ingest.ts +63 -0
- package/src/tools/lint.ts +74 -0
- package/src/tools/migrate.ts +44 -0
- package/src/tools/move.ts +79 -0
- package/src/tools/query.ts +63 -0
- package/src/tools/schemas.ts +157 -0
- package/src/tools/shared.ts +35 -0
- package/src/tools/summarize.ts +89 -0
- package/src/tools/write.ts +252 -0
- package/src/tools.ts +18 -1046
- package/src/wiki.ts +1 -0
- package/dist/daemon.d.ts +0 -49
- package/dist/daemon.d.ts.map +0 -1
- package/dist/daemon.js +0 -226
- package/dist/daemon.js.map +0 -1
- package/dist/link-discovery.d.ts +0 -40
- package/dist/link-discovery.d.ts.map +0 -1
- package/dist/link-discovery.js +0 -122
- package/dist/link-discovery.js.map +0 -1
- package/dist/maintainer.d.ts +0 -24
- package/dist/maintainer.d.ts.map +0 -1
- package/dist/maintainer.js +0 -358
- package/dist/maintainer.js.map +0 -1
- package/dist/watcher.d.ts +0 -25
- package/dist/watcher.d.ts.map +0 -1
- package/dist/watcher.js +0 -84
- package/dist/watcher.js.map +0 -1
- package/dist/webui/client/dist/index.html +0 -1885
- package/dist/webui/server.d.ts +0 -31
- package/dist/webui/server.d.ts.map +0 -1
- package/dist/webui/server.js +0 -566
- package/dist/webui/server.js.map +0 -1
- package/scripts/build-assets.mjs +0 -17
- package/src/daemon.ts +0 -288
- package/src/link-discovery.ts +0 -170
- package/src/maintainer.ts +0 -404
- package/src/python/__pycache__/minimax_lm.cpython-312.pyc +0 -0
- package/src/python/minimax_lm.py +0 -198
- package/src/python/rlm_capture.py +0 -215
- package/src/watcher.ts +0 -101
- package/src/webui/client/dist/index.html +0 -1885
- package/src/webui/server.ts +0 -765
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { QMDStore } from "qmd-engine";
|
|
2
|
+
import { enqueueWikiMaintenance } from "../scheduler/index.js";
|
|
3
|
+
import { PARA_CATEGORIES, type ParaCategory } from "../wiki.js";
|
|
4
|
+
|
|
5
|
+
// -- Source resolution helpers -----------------------------------------------
|
|
6
|
+
|
|
7
|
+
/** Resolve a page path like "projects/auth-refactor" into category + slug. */
|
|
8
|
+
export function parsePagePath(
|
|
9
|
+
path: string,
|
|
10
|
+
): { category: ParaCategory; slug: string } | null {
|
|
11
|
+
const parts = path.split("/");
|
|
12
|
+
if (parts.length === 2) {
|
|
13
|
+
const cat = parts[0] as ParaCategory;
|
|
14
|
+
if (PARA_CATEGORIES.includes(cat)) {
|
|
15
|
+
const slug = parts[1].replace(/\.md$/, "");
|
|
16
|
+
return { category: cat, slug };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// -- Background maintenance --------------------------------------------------
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Schedule index rebuild + QMD reindex after latency-sensitive edits.
|
|
26
|
+
* Debounced per wiki directory and coordinated through the scheduler queue so
|
|
27
|
+
* multiple Pi processes do not run the same maintenance task concurrently.
|
|
28
|
+
*/
|
|
29
|
+
export function scheduleWikiMaintenance(
|
|
30
|
+
wikiDir: string,
|
|
31
|
+
store: QMDStore,
|
|
32
|
+
markDirty: () => void,
|
|
33
|
+
): void {
|
|
34
|
+
enqueueWikiMaintenance(wikiDir, store, markDirty);
|
|
35
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { AgentToolResult } from "@earendil-works/pi-agent-core";
|
|
2
|
+
import type { ProjectScope } from "../scope.js";
|
|
3
|
+
import { generateOverviewPrompt } from "../summarize.js";
|
|
4
|
+
import { listPages, readPage, PARA_CATEGORIES, type ParaCategory, type WikiPage } from "../wiki.js";
|
|
5
|
+
import type { WikiSummarizeDetails } from "./schemas.js";
|
|
6
|
+
import { parsePagePath } from "./shared.js";
|
|
7
|
+
|
|
8
|
+
// -- Factory: wiki_summarize execute -----------------------------------------
|
|
9
|
+
|
|
10
|
+
export function createSummarizeExecute(
|
|
11
|
+
wikiDir: string,
|
|
12
|
+
getScope: () => ProjectScope,
|
|
13
|
+
) {
|
|
14
|
+
return async (
|
|
15
|
+
params: { target: string; depth?: "brief" | "detailed" },
|
|
16
|
+
): Promise<AgentToolResult<WikiSummarizeDetails>> => {
|
|
17
|
+
const scope = getScope();
|
|
18
|
+
const pages: WikiPage[] = [];
|
|
19
|
+
|
|
20
|
+
if (params.target === "all") {
|
|
21
|
+
// Summarize entire wiki
|
|
22
|
+
const refs = await listPages(wikiDir);
|
|
23
|
+
for (const ref of refs) {
|
|
24
|
+
const page = await readPage(wikiDir, ref.category, ref.slug);
|
|
25
|
+
if (page) pages.push(page);
|
|
26
|
+
}
|
|
27
|
+
} else if (PARA_CATEGORIES.includes(params.target as ParaCategory)) {
|
|
28
|
+
// Summarize a category
|
|
29
|
+
const refs = await listPages(wikiDir, params.target as ParaCategory);
|
|
30
|
+
for (const ref of refs) {
|
|
31
|
+
const page = await readPage(wikiDir, ref.category, ref.slug);
|
|
32
|
+
if (page) pages.push(page);
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
// Summarize a single page
|
|
36
|
+
const parsed = parsePagePath(params.target);
|
|
37
|
+
if (parsed) {
|
|
38
|
+
const page = await readPage(wikiDir, parsed.category, parsed.slug);
|
|
39
|
+
if (page) pages.push(page);
|
|
40
|
+
} else {
|
|
41
|
+
// Try finding by slug alone across categories
|
|
42
|
+
const allPages = await listPages(wikiDir);
|
|
43
|
+
const targetLower = params.target.toLowerCase();
|
|
44
|
+
for (const ref of allPages) {
|
|
45
|
+
if (ref.slug === targetLower || ref.title.toLowerCase() === targetLower) {
|
|
46
|
+
const page = await readPage(wikiDir, ref.category, ref.slug);
|
|
47
|
+
if (page) pages.push(page);
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (pages.length === 0) {
|
|
55
|
+
return {
|
|
56
|
+
content: [
|
|
57
|
+
{
|
|
58
|
+
type: "text",
|
|
59
|
+
text: `No pages found for target "${params.target}". Nothing to summarize.`,
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
details: { target: params.target, pageCount: 0 },
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Generate a bounded overview prompt for the LLM. For large targets like
|
|
67
|
+
// `all`, brief mode must not dump every full page body into model context.
|
|
68
|
+
const depth = params.depth ?? "brief";
|
|
69
|
+
const overviewPrompt = generateOverviewPrompt(pages, scope, { depth });
|
|
70
|
+
const depthNote =
|
|
71
|
+
depth === "detailed"
|
|
72
|
+
? "\nProvide a DETAILED summary with full Key Facts, Insights, and Connections for each theme."
|
|
73
|
+
: "\nProvide a BRIEF overview — one paragraph per theme, focus on high-level patterns.";
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
content: [
|
|
77
|
+
{
|
|
78
|
+
type: "text",
|
|
79
|
+
text: overviewPrompt + depthNote +
|
|
80
|
+
"\n\nYou may optionally create a summary page via wiki_write if the overview is worth preserving.",
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
details: {
|
|
84
|
+
target: params.target,
|
|
85
|
+
pageCount: pages.length,
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import type { AgentToolResult } from "@earendil-works/pi-agent-core";
|
|
2
|
+
import type { QMDStore } from "qmd-engine";
|
|
3
|
+
import type { ProjectScope } from "../scope.js";
|
|
4
|
+
import { normalizeTags, normalizeScopes } from "../tag-registry.js";
|
|
5
|
+
import { redactSecrets } from "../redact.js";
|
|
6
|
+
import { autoLinkSlugs, syncFrontmatterLinks } from "../link-utils.js";
|
|
7
|
+
import { validateFrontmatter } from "../frontmatter.js";
|
|
8
|
+
import { appendLog, gitCommit, listPageSlugs, readPage, rebuildIndex, writePage, type ParaCategory, type WikiPage } from "../wiki.js";
|
|
9
|
+
import type { WikiWriteDetails } from "./schemas.js";
|
|
10
|
+
import { scheduleWikiMaintenance } from "./shared.js";
|
|
11
|
+
|
|
12
|
+
// -- Factory: wiki_write execute ---------------------------------------------
|
|
13
|
+
|
|
14
|
+
export function createWriteExecute(
|
|
15
|
+
wikiDir: string,
|
|
16
|
+
store: QMDStore,
|
|
17
|
+
getScope: () => ProjectScope,
|
|
18
|
+
markDirty: () => void,
|
|
19
|
+
) {
|
|
20
|
+
return async (
|
|
21
|
+
params: {
|
|
22
|
+
pages: Array<{
|
|
23
|
+
category: ParaCategory;
|
|
24
|
+
slug: string;
|
|
25
|
+
title: string;
|
|
26
|
+
scope: string[];
|
|
27
|
+
tags: string[];
|
|
28
|
+
body: string;
|
|
29
|
+
mode: "create" | "replace" | "append" | "edit";
|
|
30
|
+
edits?: Array<{ oldText: string; newText: string }>;
|
|
31
|
+
}>;
|
|
32
|
+
indexContent?: string;
|
|
33
|
+
logSummary?: string;
|
|
34
|
+
},
|
|
35
|
+
): Promise<AgentToolResult<WikiWriteDetails>> => {
|
|
36
|
+
const pagesWritten: string[] = [];
|
|
37
|
+
const pagesSkipped: string[] = [];
|
|
38
|
+
const now = new Date().toISOString();
|
|
39
|
+
const scope = getScope();
|
|
40
|
+
|
|
41
|
+
// Gather all existing slugs for auto-linking (slug-only readdir scan;
|
|
42
|
+
// reading/parsing every page here made wiki_write scale poorly)
|
|
43
|
+
const allSlugs = await listPageSlugs(wikiDir);
|
|
44
|
+
|
|
45
|
+
for (const pageSpec of params.pages) {
|
|
46
|
+
// Sanitize slug
|
|
47
|
+
const slug = pageSpec.slug
|
|
48
|
+
.toLowerCase()
|
|
49
|
+
.replace(/[^a-z0-9-]/g, "-")
|
|
50
|
+
.replace(/-+/g, "-")
|
|
51
|
+
.replace(/^-|-$/g, "");
|
|
52
|
+
|
|
53
|
+
if (!slug) {
|
|
54
|
+
continue; // skip invalid slugs
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const existing = await readPage(wikiDir, pageSpec.category, slug);
|
|
58
|
+
const pagePath = `${pageSpec.category}/${slug}`;
|
|
59
|
+
|
|
60
|
+
// Track this slug for auto-linking other pages in this batch
|
|
61
|
+
allSlugs.add(slug);
|
|
62
|
+
|
|
63
|
+
if (pageSpec.mode === "create" && existing) {
|
|
64
|
+
pagesSkipped.push(`${pagePath} (already exists; use mode=replace, mode=append, or wiki_edit)`);
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (pageSpec.mode === "edit" && !existing) {
|
|
69
|
+
pagesSkipped.push(`${pagePath} (missing; wiki_write mode=edit requires an existing page)`);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (pageSpec.mode === "edit" && existing) {
|
|
74
|
+
// Legacy edit mode: keep for compatibility, but make it atomic like wiki_edit.
|
|
75
|
+
const edits = pageSpec.edits ?? [];
|
|
76
|
+
if (edits.length === 0) {
|
|
77
|
+
continue; // no edits to apply
|
|
78
|
+
}
|
|
79
|
+
const errors: string[] = [];
|
|
80
|
+
for (const edit of edits) {
|
|
81
|
+
const first = existing.body.indexOf(edit.oldText);
|
|
82
|
+
const last = existing.body.lastIndexOf(edit.oldText);
|
|
83
|
+
if (first === -1) {
|
|
84
|
+
errors.push(`oldText not found: "${edit.oldText.slice(0, 60)}..."`);
|
|
85
|
+
} else if (first !== last) {
|
|
86
|
+
errors.push(`oldText is not unique: "${edit.oldText.slice(0, 60)}..."`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (errors.length > 0) {
|
|
90
|
+
pagesSkipped.push(`${pagePath} (${errors.join("; ")})`);
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
let editedBody = existing.body;
|
|
94
|
+
for (const edit of edits) {
|
|
95
|
+
editedBody = editedBody.replace(edit.oldText, edit.newText);
|
|
96
|
+
}
|
|
97
|
+
const linkedBody = redactSecrets(autoLinkSlugs(editedBody, allSlugs, slug)).text;
|
|
98
|
+
const rawScope = pageSpec.scope.length > 0 ? pageSpec.scope : existing.frontmatter.scope;
|
|
99
|
+
const newScope = normalizeScopes(rawScope);
|
|
100
|
+
const newTags = pageSpec.tags.length > 0 ? pageSpec.tags : existing.frontmatter.tags;
|
|
101
|
+
const updatedPage: WikiPage = {
|
|
102
|
+
category: pageSpec.category,
|
|
103
|
+
slug,
|
|
104
|
+
frontmatter: {
|
|
105
|
+
...existing.frontmatter,
|
|
106
|
+
title: pageSpec.title || existing.frontmatter.title,
|
|
107
|
+
scope: newScope,
|
|
108
|
+
tags: normalizeTags(newTags, newScope),
|
|
109
|
+
updated: now,
|
|
110
|
+
links: syncFrontmatterLinks(linkedBody),
|
|
111
|
+
},
|
|
112
|
+
body: linkedBody,
|
|
113
|
+
};
|
|
114
|
+
await writePage(wikiDir, updatedPage);
|
|
115
|
+
pagesWritten.push(pagePath + (errors.length > 0 ? ` (${errors.length} edit(s) failed)` : ""));
|
|
116
|
+
} else if (pageSpec.mode === "append" && existing) {
|
|
117
|
+
// Append to existing page body
|
|
118
|
+
const combinedBody = existing.body.trimEnd() + "\n\n" + pageSpec.body;
|
|
119
|
+
const linkedBody = redactSecrets(autoLinkSlugs(combinedBody, allSlugs, slug)).text;
|
|
120
|
+
const mergedTags = [...new Set([...existing.frontmatter.tags, ...pageSpec.tags])];
|
|
121
|
+
const mergedScope = normalizeScopes([...new Set([...existing.frontmatter.scope, ...pageSpec.scope])]);
|
|
122
|
+
const updatedPage: WikiPage = {
|
|
123
|
+
...existing,
|
|
124
|
+
body: linkedBody,
|
|
125
|
+
frontmatter: {
|
|
126
|
+
...existing.frontmatter,
|
|
127
|
+
updated: now,
|
|
128
|
+
tags: normalizeTags(mergedTags, mergedScope),
|
|
129
|
+
scope: mergedScope,
|
|
130
|
+
links: syncFrontmatterLinks(linkedBody),
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
await writePage(wikiDir, updatedPage);
|
|
134
|
+
pagesWritten.push(pagePath);
|
|
135
|
+
} else if (pageSpec.mode === "replace" && existing) {
|
|
136
|
+
// Replace existing page body, update frontmatter
|
|
137
|
+
const linkedBody = redactSecrets(autoLinkSlugs(pageSpec.body, allSlugs, slug)).text;
|
|
138
|
+
const rawScope = pageSpec.scope.length > 0 ? pageSpec.scope : existing.frontmatter.scope;
|
|
139
|
+
const newScope = normalizeScopes(rawScope);
|
|
140
|
+
const newTags = pageSpec.tags.length > 0 ? pageSpec.tags : existing.frontmatter.tags;
|
|
141
|
+
const updatedPage: WikiPage = {
|
|
142
|
+
category: pageSpec.category,
|
|
143
|
+
slug,
|
|
144
|
+
frontmatter: {
|
|
145
|
+
...existing.frontmatter,
|
|
146
|
+
title: pageSpec.title,
|
|
147
|
+
para: pageSpec.category,
|
|
148
|
+
scope: newScope,
|
|
149
|
+
tags: normalizeTags(newTags, newScope),
|
|
150
|
+
updated: now,
|
|
151
|
+
links: syncFrontmatterLinks(linkedBody),
|
|
152
|
+
},
|
|
153
|
+
body: linkedBody,
|
|
154
|
+
};
|
|
155
|
+
await writePage(wikiDir, updatedPage);
|
|
156
|
+
pagesWritten.push(pagePath);
|
|
157
|
+
} else {
|
|
158
|
+
// Create new page (or mode=create/replace on non-existing)
|
|
159
|
+
const linkedBody = redactSecrets(autoLinkSlugs(pageSpec.body, allSlugs, slug)).text;
|
|
160
|
+
const rawScope = pageSpec.scope.length > 0 ? pageSpec.scope : [scope.name];
|
|
161
|
+
const newScope = normalizeScopes(rawScope);
|
|
162
|
+
const frontmatter = validateFrontmatter({
|
|
163
|
+
title: pageSpec.title,
|
|
164
|
+
para: pageSpec.category,
|
|
165
|
+
scope: newScope,
|
|
166
|
+
tags: normalizeTags(pageSpec.tags, newScope),
|
|
167
|
+
sources: [],
|
|
168
|
+
created: now,
|
|
169
|
+
updated: now,
|
|
170
|
+
links: syncFrontmatterLinks(linkedBody),
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
const newPage: WikiPage = {
|
|
174
|
+
category: pageSpec.category,
|
|
175
|
+
slug,
|
|
176
|
+
frontmatter,
|
|
177
|
+
body: linkedBody,
|
|
178
|
+
};
|
|
179
|
+
await writePage(wikiDir, newPage);
|
|
180
|
+
pagesWritten.push(pagePath);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Always auto-rebuild index from disk.
|
|
185
|
+
// The LLM's indexContent is unreliable — it only knows about pages
|
|
186
|
+
// in its context, so it produces partial indexes that overwrite
|
|
187
|
+
// the full one. indexContent parameter is deprecated and ignored.
|
|
188
|
+
let indexUpdated = false;
|
|
189
|
+
if (pagesWritten.length > 0) {
|
|
190
|
+
await rebuildIndex(wikiDir);
|
|
191
|
+
indexUpdated = true;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Append to log.md if summary provided
|
|
195
|
+
let logAppended = false;
|
|
196
|
+
if (params.logSummary && pagesWritten.length > 0) {
|
|
197
|
+
await appendLog(wikiDir, {
|
|
198
|
+
date: now.split("T")[0],
|
|
199
|
+
operation: "ingest",
|
|
200
|
+
summary: params.logSummary,
|
|
201
|
+
pages: pagesWritten,
|
|
202
|
+
});
|
|
203
|
+
logAppended = true;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Defer QMD BM25 reindex to the debounced background maintenance queue
|
|
207
|
+
// (same as wiki_edit). Immediate post-write queries are safe: queryWiki
|
|
208
|
+
// retries with a fresh store.update() before returning zero results.
|
|
209
|
+
if (pagesWritten.length > 0) {
|
|
210
|
+
scheduleWikiMaintenance(wikiDir, store, markDirty);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Mark context cache dirty so before_agent_start rebuilds
|
|
214
|
+
markDirty();
|
|
215
|
+
|
|
216
|
+
// Git auto-commit
|
|
217
|
+
if (pagesWritten.length > 0) {
|
|
218
|
+
const commitMsg = params.logSummary
|
|
219
|
+
? params.logSummary
|
|
220
|
+
: `wiki: ${pagesWritten.join(", ")}`;
|
|
221
|
+
await gitCommit(wikiDir, commitMsg);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const summary = [
|
|
225
|
+
pagesWritten.length > 0
|
|
226
|
+
? `Wrote ${pagesWritten.length} page(s): ${pagesWritten.join(", ")}`
|
|
227
|
+
: "No pages written.",
|
|
228
|
+
pagesSkipped.length > 0 ? `Skipped ${pagesSkipped.length} page(s): ${pagesSkipped.join(", ")}` : "",
|
|
229
|
+
].filter(Boolean).join("\n");
|
|
230
|
+
|
|
231
|
+
return {
|
|
232
|
+
content: [
|
|
233
|
+
{
|
|
234
|
+
type: "text",
|
|
235
|
+
text: [
|
|
236
|
+
summary,
|
|
237
|
+
indexUpdated ? "Updated index.md." : "",
|
|
238
|
+
logAppended ? `Logged: ${params.logSummary}` : "",
|
|
239
|
+
]
|
|
240
|
+
.filter(Boolean)
|
|
241
|
+
.join("\n"),
|
|
242
|
+
},
|
|
243
|
+
],
|
|
244
|
+
details: {
|
|
245
|
+
pagesWritten,
|
|
246
|
+
indexUpdated,
|
|
247
|
+
logAppended,
|
|
248
|
+
pagesSkipped,
|
|
249
|
+
},
|
|
250
|
+
};
|
|
251
|
+
};
|
|
252
|
+
}
|