@zosmaai/pi-llm-wiki 0.11.6 → 0.11.8
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.de.md +1 -0
- package/README.es.md +1 -0
- package/README.fr.md +1 -0
- package/README.hi.md +1 -0
- package/README.ja.md +1 -0
- package/README.ko.md +1 -0
- package/README.md +8 -0
- package/README.pt.md +1 -0
- package/README.ru.md +1 -0
- package/README.zh.md +1 -0
- package/dist/extensions/llm-wiki/lib/dashboard-command.js +7 -2
- package/dist/extensions/llm-wiki/lib/dashboard.js +1 -1
- package/dist/extensions/llm-wiki/lib/host.js +1 -1
- package/dist/extensions/llm-wiki/lib/ingest-worker.js +1 -1
- package/dist/extensions/llm-wiki/lib/knowledge-links.js +1 -1
- package/dist/extensions/llm-wiki/lib/legacy-repair.js +1 -1
- package/dist/extensions/llm-wiki/lib/metadata.js +1 -1
- package/dist/extensions/llm-wiki/lib/model-command.js +77 -4
- package/dist/extensions/llm-wiki/lib/recall.js +2 -2
- package/dist/extensions/llm-wiki/lib/runtime.js +1 -1
- package/dist/extensions/llm-wiki/lib/settings-command.js +6 -1
- package/dist/extensions/llm-wiki/lib/source-extractors.js +21 -5
- package/dist/extensions/llm-wiki/lib/task-config.js +13 -0
- package/dist/extensions/llm-wiki/lib/tools.js +7 -5
- package/dist/extensions/llm-wiki/lib/trajectory.js +1 -1
- package/dist/extensions/llm-wiki/lib/utils.js +1 -1
- package/dist/extensions/llm-wiki/lib/vault-format.js +1 -1
- package/dist/extensions/llm-wiki/lib/visible-status.js +1 -1
- package/dist/mcp/operations.js +1 -1
- package/docs/superpowers/plans/2026-08-29-custom-wiki-page-types.md +378 -0
- package/docs/superpowers/plans/2026-08-29-keyless-provider-ingest-fix.md +256 -0
- package/extensions/llm-wiki/lib/bootstrap.ts +2 -2
- package/extensions/llm-wiki/lib/dashboard-command.ts +9 -3
- package/extensions/llm-wiki/lib/dashboard.ts +1 -1
- package/extensions/llm-wiki/lib/embeddings.ts +1 -1
- package/extensions/llm-wiki/lib/guardrails.ts +2 -2
- package/extensions/llm-wiki/lib/host.ts +1 -1
- package/extensions/llm-wiki/lib/ingest-worker.ts +6 -6
- package/extensions/llm-wiki/lib/knowledge-links.ts +1 -1
- package/extensions/llm-wiki/lib/legacy-repair.ts +4 -4
- package/extensions/llm-wiki/lib/metadata.ts +3 -3
- package/extensions/llm-wiki/lib/model-command.ts +116 -6
- package/extensions/llm-wiki/lib/observation.ts +2 -2
- package/extensions/llm-wiki/lib/recall.ts +4 -4
- package/extensions/llm-wiki/lib/retro.ts +1 -1
- package/extensions/llm-wiki/lib/runtime.ts +1 -1
- package/extensions/llm-wiki/lib/settings-command.ts +9 -2
- package/extensions/llm-wiki/lib/source-extractors.ts +20 -12
- package/extensions/llm-wiki/lib/source-packet.ts +2 -3
- package/extensions/llm-wiki/lib/task-config.ts +24 -1
- package/extensions/llm-wiki/lib/tools.ts +9 -15
- package/extensions/llm-wiki/lib/trajectory.ts +2 -2
- package/extensions/llm-wiki/lib/utils.ts +1 -1
- package/extensions/llm-wiki/lib/vault-format.ts +2 -2
- package/extensions/llm-wiki/lib/visible-status.ts +1 -1
- package/extensions/llm-wiki/lib/wiki-service.ts +1 -1
- package/mcp/operations.ts +3 -3
- package/package.json +14 -9
package/README.de.md
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
[](https://www.npmjs.com/package/@zosmaai/pi-llm-wiki)
|
|
10
10
|
[](https://codecov.io/gh/zosmaai/pi-llm-wiki)
|
|
11
11
|
[](LICENSE)
|
|
12
|
+
[](https://zosmaai.github.io/pi-llm-wiki/)
|
|
12
13
|
[](https://github.com/zosmaai/pi-llm-wiki/actions/workflows/codeql.yml)
|
|
13
14
|
[](https://github.com/zosmaai/pi-llm-wiki/stargazers)
|
|
14
15
|
|
package/README.es.md
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
[](https://www.npmjs.com/package/@zosmaai/pi-llm-wiki)
|
|
10
10
|
[](https://codecov.io/gh/zosmaai/pi-llm-wiki)
|
|
11
11
|
[](LICENSE)
|
|
12
|
+
[](https://zosmaai.github.io/pi-llm-wiki/)
|
|
12
13
|
[](https://github.com/zosmaai/pi-llm-wiki/actions/workflows/codeql.yml)
|
|
13
14
|
[](https://github.com/zosmaai/pi-llm-wiki/stargazers)
|
|
14
15
|
|
package/README.fr.md
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
[](https://www.npmjs.com/package/@zosmaai/pi-llm-wiki)
|
|
10
10
|
[](https://codecov.io/gh/zosmaai/pi-llm-wiki)
|
|
11
11
|
[](LICENSE)
|
|
12
|
+
[](https://zosmaai.github.io/pi-llm-wiki/)
|
|
12
13
|
[](https://github.com/zosmaai/pi-llm-wiki/actions/workflows/codeql.yml)
|
|
13
14
|
[](https://github.com/zosmaai/pi-llm-wiki/stargazers)
|
|
14
15
|
|
package/README.hi.md
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
[](https://www.npmjs.com/package/@zosmaai/pi-llm-wiki)
|
|
10
10
|
[](https://codecov.io/gh/zosmaai/pi-llm-wiki)
|
|
11
11
|
[](LICENSE)
|
|
12
|
+
[](https://zosmaai.github.io/pi-llm-wiki/)
|
|
12
13
|
[](https://github.com/zosmaai/pi-llm-wiki/actions/workflows/codeql.yml)
|
|
13
14
|
[](https://github.com/zosmaai/pi-llm-wiki/stargazers)
|
|
14
15
|
|
package/README.ja.md
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
[](https://www.npmjs.com/package/@zosmaai/pi-llm-wiki)
|
|
10
10
|
[](https://codecov.io/gh/zosmaai/pi-llm-wiki)
|
|
11
11
|
[](LICENSE)
|
|
12
|
+
[](https://zosmaai.github.io/pi-llm-wiki/)
|
|
12
13
|
[](https://github.com/zosmaai/pi-llm-wiki/actions/workflows/codeql.yml)
|
|
13
14
|
[](https://github.com/zosmaai/pi-llm-wiki/stargazers)
|
|
14
15
|
|
package/README.ko.md
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
[](https://www.npmjs.com/package/@zosmaai/pi-llm-wiki)
|
|
10
10
|
[](https://codecov.io/gh/zosmaai/pi-llm-wiki)
|
|
11
11
|
[](LICENSE)
|
|
12
|
+
[](https://zosmaai.github.io/pi-llm-wiki/)
|
|
12
13
|
[](https://github.com/zosmaai/pi-llm-wiki/actions/workflows/codeql.yml)
|
|
13
14
|
[](https://github.com/zosmaai/pi-llm-wiki/stargazers)
|
|
14
15
|
|
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
[](https://www.npmjs.com/package/@zosmaai/pi-llm-wiki)
|
|
10
10
|
[](https://codecov.io/gh/zosmaai/pi-llm-wiki)
|
|
11
11
|
[](LICENSE)
|
|
12
|
+
[](https://zosmaai.github.io/pi-llm-wiki/)
|
|
12
13
|
[](https://github.com/zosmaai/pi-llm-wiki/actions/workflows/codeql.yml)
|
|
13
14
|
[](https://github.com/zosmaai/pi-llm-wiki/stargazers)
|
|
14
15
|
|
|
@@ -604,6 +605,13 @@ Thanks to everyone who has contributed! This list is regenerated automatically b
|
|
|
604
605
|
<sub><b>Superdao</b></sub>
|
|
605
606
|
</a>
|
|
606
607
|
</td>
|
|
608
|
+
<td align="center">
|
|
609
|
+
<a href="https://github.com/wooksong">
|
|
610
|
+
<img src="https://avatars.githubusercontent.com/u/2772376?v=4" width="64;" alt="wooksong"/>
|
|
611
|
+
<br />
|
|
612
|
+
<sub><b>wooksong</b></sub>
|
|
613
|
+
</a>
|
|
614
|
+
</td>
|
|
607
615
|
<td align="center">
|
|
608
616
|
<a href="https://github.com/mystery4f">
|
|
609
617
|
<img src="https://avatars.githubusercontent.com/u/40482524?v=4" width="64;" alt="mystery4f"/>
|
package/README.pt.md
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
[](https://www.npmjs.com/package/@zosmaai/pi-llm-wiki)
|
|
10
10
|
[](https://codecov.io/gh/zosmaai/pi-llm-wiki)
|
|
11
11
|
[](LICENSE)
|
|
12
|
+
[](https://zosmaai.github.io/pi-llm-wiki/)
|
|
12
13
|
[](https://github.com/zosmaai/pi-llm-wiki/actions/workflows/codeql.yml)
|
|
13
14
|
[](https://github.com/zosmaai/pi-llm-wiki/stargazers)
|
|
14
15
|
|
package/README.ru.md
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
[](https://www.npmjs.com/package/@zosmaai/pi-llm-wiki)
|
|
10
10
|
[](https://codecov.io/gh/zosmaai/pi-llm-wiki)
|
|
11
11
|
[](LICENSE)
|
|
12
|
+
[](https://zosmaai.github.io/pi-llm-wiki/)
|
|
12
13
|
[](https://github.com/zosmaai/pi-llm-wiki/actions/workflows/codeql.yml)
|
|
13
14
|
[](https://github.com/zosmaai/pi-llm-wiki/stargazers)
|
|
14
15
|
|
package/README.zh.md
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
[](https://www.npmjs.com/package/@zosmaai/pi-llm-wiki)
|
|
10
10
|
[](https://codecov.io/gh/zosmaai/pi-llm-wiki)
|
|
11
11
|
[](LICENSE)
|
|
12
|
+
[](https://zosmaai.github.io/pi-llm-wiki/)
|
|
12
13
|
[](https://github.com/zosmaai/pi-llm-wiki/actions/workflows/codeql.yml)
|
|
13
14
|
[](https://github.com/zosmaai/pi-llm-wiki/stargazers)
|
|
14
15
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Container,
|
|
1
|
+
import { Container, matchesKey, Text } from "@mariozechner/pi-tui";
|
|
2
2
|
import { collectDashboardStats } from "./dashboard.js";
|
|
3
3
|
const TYPE_ORDER = [
|
|
4
4
|
"concept",
|
|
@@ -65,6 +65,11 @@ export class DashboardScreen extends Container {
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
|
+
// ponytail: overlay options matching pi-blackhole's config modal style
|
|
69
|
+
const OVERLAY_OPTS = {
|
|
70
|
+
overlay: true,
|
|
71
|
+
overlayOptions: { anchor: "center", width: "92%", maxHeight: "95%" },
|
|
72
|
+
};
|
|
68
73
|
/**
|
|
69
74
|
* Register the /wiki-dashboard command.
|
|
70
75
|
*/
|
|
@@ -80,7 +85,7 @@ export function registerWikiDashboardCommand(pi, runtime) {
|
|
|
80
85
|
const stats = await collectDashboardStats(ctx.cwd);
|
|
81
86
|
await ctx.ui.custom((_tui, _theme, _keybindings, close) => {
|
|
82
87
|
return new DashboardScreen(renderStatsLines(stats), close);
|
|
83
|
-
});
|
|
88
|
+
}, OVERLAY_OPTS);
|
|
84
89
|
},
|
|
85
90
|
});
|
|
86
91
|
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*
|
|
12
12
|
* No writes, no LLM calls, no new files. Pure reader.
|
|
13
13
|
*/
|
|
14
|
-
import {
|
|
14
|
+
import { readdir, readFile, stat } from "node:fs/promises";
|
|
15
15
|
import { readJson, resolveVaultPaths } from "./utils.js";
|
|
16
16
|
/** Directories excluded from the page walk (infrastructure, not pages). */
|
|
17
17
|
const SKIP_DIRS = new Set([
|
|
@@ -100,7 +100,7 @@ export function resolveProjectSettingsPath(cwd, host = detectHost()) {
|
|
|
100
100
|
*
|
|
101
101
|
* Always writes to `settings.json` inside the agent dir — both hosts read it.
|
|
102
102
|
*/
|
|
103
|
-
export function resolveGlobalSettingsPath(
|
|
103
|
+
export function resolveGlobalSettingsPath(_host = detectHost()) {
|
|
104
104
|
let agentDir = "";
|
|
105
105
|
try {
|
|
106
106
|
agentDir = getAgentDir();
|
|
@@ -7,7 +7,7 @@ import { appendEvent, rebuildMetadataLight } from "./metadata.js";
|
|
|
7
7
|
import { runSubAgent } from "./subagent.js";
|
|
8
8
|
import { resolveWikilinkValidation } from "./task-config.js";
|
|
9
9
|
import { fmtDate, readJson, slugify } from "./utils.js";
|
|
10
|
-
import {
|
|
10
|
+
import { assertWritableVault, VaultWriteError } from "./vault-format.js";
|
|
11
11
|
/**
|
|
12
12
|
* Background ingest synthesis (issue #65, part of epic #63).
|
|
13
13
|
*
|
|
@@ -158,7 +158,7 @@ function resolveMarkdownTarget(target, sourceId) {
|
|
|
158
158
|
}
|
|
159
159
|
// Convert decoded backslashes to /
|
|
160
160
|
const normalized = decoded.map((s) => s.replace(/\\/g, "/")).join("/");
|
|
161
|
-
const sourceDir = sourceId.replace(/[
|
|
161
|
+
const sourceDir = sourceId.replace(/[^/]*$/, ""); // directory of source
|
|
162
162
|
const parts = normalized.split("/");
|
|
163
163
|
const isRootRelative = normalized.startsWith("/");
|
|
164
164
|
if (isRootRelative) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
-
import {
|
|
2
|
+
import { chmodSync, closeSync, constants, existsSync, fstatSync, fsyncSync, linkSync, lstatSync, mkdirSync, openSync, readdirSync, readFileSync, renameSync, unlinkSync, utimesSync, writeFileSync, } from "node:fs";
|
|
3
3
|
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
4
4
|
import { createKnowledgeDocument, parseKnowledgeDocument, parseMarkdownFrontmatter, serializeKnowledgeDocument, } from "./knowledge-document.js";
|
|
5
5
|
import { readJson } from "./utils.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { existsSync, lstatSync, mkdirSync,
|
|
2
|
+
import { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync, } from "node:fs";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { buildResolvedBacklinks, buildWikilinkIndex, } from "./knowledge-links.js";
|
|
5
5
|
import { isPathWithin, readJson } from "./utils.js";
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
import { Container, matchesKey, SelectList, Spacer, Text, } from "@mariozechner/pi-tui";
|
|
1
2
|
import { parseModelRef, persistTaskModel } from "./task-config.js";
|
|
2
3
|
/** Words that clear the override and revert to the session model. */
|
|
3
4
|
const CLEAR_WORDS = new Set(["session", "default", "reset", "clear", "none", "unset"]);
|
|
5
|
+
/** Sentinel value for the "use session model" picker row — not a valid provider/id. */
|
|
6
|
+
const SESSION_VALUE = "__session__";
|
|
7
|
+
/** Same window size as pi's built-in `/model` picker. */
|
|
8
|
+
const MAX_VISIBLE = 10;
|
|
4
9
|
/** The status-bar key for the active-model label (so we can update it in place). */
|
|
5
10
|
export const MODEL_STATUS_KEY = "llm-wiki-model";
|
|
6
11
|
/**
|
|
@@ -17,6 +22,68 @@ export function formatActiveModelLabel(config, sessionModelId) {
|
|
|
17
22
|
function modelRef(m) {
|
|
18
23
|
return `${m.provider}/${m.id}`;
|
|
19
24
|
}
|
|
25
|
+
function buildSelectTheme(theme) {
|
|
26
|
+
return {
|
|
27
|
+
selectedPrefix: (text) => theme.fg("accent", text),
|
|
28
|
+
selectedText: (text) => theme.fg("accent", text),
|
|
29
|
+
description: (text) => theme.fg("dim", text),
|
|
30
|
+
scrollInfo: (text) => theme.fg("dim", text),
|
|
31
|
+
noMatch: (text) => theme.fg("muted", text),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function buildPickerItems(pool, currentRef) {
|
|
35
|
+
const items = [
|
|
36
|
+
{
|
|
37
|
+
value: SESSION_VALUE,
|
|
38
|
+
label: "↩ Use session model (clear override)",
|
|
39
|
+
description: currentRef ? undefined : "current",
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
let selectedIndex = 0;
|
|
43
|
+
for (const m of pool) {
|
|
44
|
+
const ref = modelRef(m);
|
|
45
|
+
const isCurrent = currentRef === ref;
|
|
46
|
+
items.push({
|
|
47
|
+
value: ref,
|
|
48
|
+
label: ref,
|
|
49
|
+
description: isCurrent ? "current" : undefined,
|
|
50
|
+
});
|
|
51
|
+
if (isCurrent)
|
|
52
|
+
selectedIndex = items.length - 1;
|
|
53
|
+
}
|
|
54
|
+
return { items, selectedIndex };
|
|
55
|
+
}
|
|
56
|
+
/** Editor-dock picker; `ui.custom` without overlay replaces the input slot like `/model`. */
|
|
57
|
+
class ModelPickerScreen extends Container {
|
|
58
|
+
list;
|
|
59
|
+
doneFn;
|
|
60
|
+
closed = false;
|
|
61
|
+
constructor(title, items, selectedIndex, theme, done) {
|
|
62
|
+
super();
|
|
63
|
+
this.doneFn = done;
|
|
64
|
+
this.addChild(new Text(title, 0, 0));
|
|
65
|
+
this.addChild(new Spacer(1));
|
|
66
|
+
this.list = new SelectList(items, Math.min(MAX_VISIBLE, Math.max(items.length, 1)), buildSelectTheme(theme));
|
|
67
|
+
this.list.setSelectedIndex(selectedIndex);
|
|
68
|
+
this.list.onSelect = (item) => this.finish(item.value);
|
|
69
|
+
this.list.onCancel = () => this.finish(undefined);
|
|
70
|
+
this.addChild(this.list);
|
|
71
|
+
}
|
|
72
|
+
handleInput(data) {
|
|
73
|
+
// matchesKey covers kitty CSI-u Esc; SelectList cancel is the fallback.
|
|
74
|
+
if (matchesKey(data, "escape")) {
|
|
75
|
+
this.finish(undefined);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
this.list.handleInput(data);
|
|
79
|
+
}
|
|
80
|
+
finish(result) {
|
|
81
|
+
if (this.closed)
|
|
82
|
+
return;
|
|
83
|
+
this.closed = true;
|
|
84
|
+
this.doneFn(result);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
20
87
|
/**
|
|
21
88
|
* Register the `/wiki-model` slash command. Lets the user view the active
|
|
22
89
|
* background task model and choose another (or revert to the session model).
|
|
@@ -66,14 +133,20 @@ export function registerWikiModelCommand(pi, runtime) {
|
|
|
66
133
|
ctx.ui.notify(`LLM Wiki: active background model is ${current}. Pass provider/id to change it (no interactive UI here).`, "info");
|
|
67
134
|
return;
|
|
68
135
|
}
|
|
136
|
+
if (typeof ctx.ui.custom !== "function") {
|
|
137
|
+
ctx.ui.notify(`LLM Wiki: this host does not support the model picker. Pass provider/id (e.g. anthropic/claude-haiku) or "session". Active: ${current}.`, "warning");
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
69
140
|
const available = ctx.modelRegistry.getAvailable() ?? [];
|
|
70
141
|
const pool = available.length > 0 ? available : ctx.modelRegistry.getAll();
|
|
71
|
-
const
|
|
72
|
-
const
|
|
73
|
-
const picked = await ctx.ui.
|
|
142
|
+
const currentRef = runtime.config.taskModel ? modelRef(runtime.config.taskModel) : undefined;
|
|
143
|
+
const { items, selectedIndex } = buildPickerItems(pool, currentRef);
|
|
144
|
+
const picked = await ctx.ui.custom((_tui, theme, _keybindings, done) => {
|
|
145
|
+
return new ModelPickerScreen(`Wiki background model (current: ${current})`, items, selectedIndex, theme, done);
|
|
146
|
+
});
|
|
74
147
|
if (picked === undefined)
|
|
75
148
|
return; // cancelled
|
|
76
|
-
if (picked ===
|
|
149
|
+
if (picked === SESSION_VALUE) {
|
|
77
150
|
apply(undefined);
|
|
78
151
|
return;
|
|
79
152
|
}
|
|
@@ -42,7 +42,7 @@ function normalizeText(value) {
|
|
|
42
42
|
return flattenSearchValue(value)
|
|
43
43
|
.toLowerCase()
|
|
44
44
|
.normalize("NFKC")
|
|
45
|
-
.replace(/[
|
|
45
|
+
.replace(/[-_./\\]+/g, " ")
|
|
46
46
|
.replace(/[\p{P}\p{S}]+/gu, " ")
|
|
47
47
|
.replace(/\s+/g, " ")
|
|
48
48
|
.trim();
|
|
@@ -236,7 +236,7 @@ function chunkPreview(heading, content) {
|
|
|
236
236
|
* Pseudo-relevance feedback: terms from top-matching pages that aren't in
|
|
237
237
|
* the original query become expansion candidates.
|
|
238
238
|
*/
|
|
239
|
-
function extractExpansionTerms(scored, originalQuery,
|
|
239
|
+
function extractExpansionTerms(scored, originalQuery, _paths, maxTerms = 6) {
|
|
240
240
|
const topResults = scored.slice(0, Math.min(3, scored.length));
|
|
241
241
|
if (topResults.length === 0)
|
|
242
242
|
return [];
|
|
@@ -280,6 +280,11 @@ class SettingsScreen extends Container {
|
|
|
280
280
|
function scopeTitle(scope) {
|
|
281
281
|
return `\u{1F9E0} LLM Wiki Settings \u2014 ${scope === "global" ? "Global" : "Project"} (Esc to close)`;
|
|
282
282
|
}
|
|
283
|
+
// ponytail: overlay options matching pi-blackhole's config modal style
|
|
284
|
+
const OVERLAY_OPTS = {
|
|
285
|
+
overlay: true,
|
|
286
|
+
overlayOptions: { anchor: "center", width: "92%", maxHeight: "95%" },
|
|
287
|
+
};
|
|
283
288
|
async function showSettingsTui(ui, cwd, scope) {
|
|
284
289
|
if (typeof ui.custom !== "function") {
|
|
285
290
|
ui.notify("LLM Wiki: this host does not support the settings screen. Edit settings.json directly.", "warning");
|
|
@@ -344,7 +349,7 @@ async function showSettingsTui(ui, cwd, scope) {
|
|
|
344
349
|
}, () => close());
|
|
345
350
|
screenRef = new SettingsScreen(scopeTitle(writeScope), list);
|
|
346
351
|
return screenRef;
|
|
347
|
-
});
|
|
352
|
+
}, OVERLAY_OPTS);
|
|
348
353
|
}
|
|
349
354
|
/**
|
|
350
355
|
* Register the /wiki-settings command.
|
|
@@ -190,7 +190,7 @@ async function extractWithMarkItDown(pi, source, signal) {
|
|
|
190
190
|
try {
|
|
191
191
|
if (!(await hasMarkItDown(pi, signal)))
|
|
192
192
|
return "";
|
|
193
|
-
const mdResult = await exec(pi, "
|
|
193
|
+
const mdResult = await exec(pi, "uvx", ["--from", "markitdown[docx,pdf]", "markitdown", source], { signal, timeout: markitdownTimeoutMs() });
|
|
194
194
|
return mdResult.stdout.trim() ? mdResult.stdout : "";
|
|
195
195
|
}
|
|
196
196
|
catch {
|
|
@@ -198,8 +198,24 @@ async function extractWithMarkItDown(pi, source, signal) {
|
|
|
198
198
|
}
|
|
199
199
|
}
|
|
200
200
|
async function hasMarkItDown(pi, signal) {
|
|
201
|
-
|
|
202
|
-
|
|
201
|
+
// Probe without shell to avoid CWE-78; try which/where then uvx --version
|
|
202
|
+
try {
|
|
203
|
+
await exec(pi, "which", ["uvx"], { signal });
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
206
|
+
catch { }
|
|
207
|
+
try {
|
|
208
|
+
await exec(pi, "where", ["uvx"], { signal });
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
catch { }
|
|
212
|
+
try {
|
|
213
|
+
await exec(pi, "uvx", ["--version"], { signal });
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
203
219
|
}
|
|
204
220
|
async function fetchTextUrl(pi, url, signal) {
|
|
205
221
|
try {
|
|
@@ -254,7 +270,7 @@ function decodeHtmlEntities(text) {
|
|
|
254
270
|
if (map[lower])
|
|
255
271
|
return map[lower];
|
|
256
272
|
if (lower.startsWith("&#"))
|
|
257
|
-
return String.fromCodePoint(Number.parseInt(entity.slice(2, -1)));
|
|
273
|
+
return String.fromCodePoint(Number.parseInt(entity.slice(2, -1), 10));
|
|
258
274
|
return entity;
|
|
259
275
|
});
|
|
260
276
|
}
|
|
@@ -271,7 +287,7 @@ function xmlToMarkdown(xml) {
|
|
|
271
287
|
let prev = "";
|
|
272
288
|
while (prev !== text) {
|
|
273
289
|
prev = text;
|
|
274
|
-
text = text.replace(/<[a-zA-Z
|
|
290
|
+
text = text.replace(/<[a-zA-Z/!?][^>]*>/g, "");
|
|
275
291
|
}
|
|
276
292
|
text = text.replace(/</g, "");
|
|
277
293
|
text = decodeHtmlEntities(text);
|
|
@@ -112,6 +112,18 @@ function readNamespacedConfig(path) {
|
|
|
112
112
|
if (typeof wl === "string" && WIKILINK_VALIDATION_MODES.includes(wl)) {
|
|
113
113
|
out.wikilinkValidation = wl;
|
|
114
114
|
}
|
|
115
|
+
const ct = section.customTypes;
|
|
116
|
+
if (ct && typeof ct === "object" && !Array.isArray(ct)) {
|
|
117
|
+
const entries = Object.entries(ct);
|
|
118
|
+
const valid = {};
|
|
119
|
+
for (const [k, v] of entries) {
|
|
120
|
+
if (typeof k === "string" && typeof v === "string" && k && v) {
|
|
121
|
+
valid[k] = v;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (Object.keys(valid).length)
|
|
125
|
+
out.customTypes = valid;
|
|
126
|
+
}
|
|
115
127
|
return out;
|
|
116
128
|
}
|
|
117
129
|
catch {
|
|
@@ -282,6 +294,7 @@ const KNOWN_KEYS = [
|
|
|
282
294
|
"synthesisLanguage",
|
|
283
295
|
"synthesisMaxTokens",
|
|
284
296
|
"wikilinkValidation",
|
|
297
|
+
"customTypes",
|
|
285
298
|
];
|
|
286
299
|
export function loadTaskConfigSources(cwd) {
|
|
287
300
|
const globalResult = {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, mkdirSync,
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join, relative } from "node:path";
|
|
3
3
|
import { Type } from "typebox";
|
|
4
4
|
import { bootstrapVault } from "./bootstrap.js";
|
|
@@ -422,7 +422,7 @@ export function registerWikiEnsurePage(pi, runtime) {
|
|
|
422
422
|
],
|
|
423
423
|
parameters: Type.Object({
|
|
424
424
|
type: Type.String({
|
|
425
|
-
description: "Page type: entity | concept | synthesis | analysis | requirement | skill | case",
|
|
425
|
+
description: "Page type: entity | concept | synthesis | analysis | requirement | skill | case (built-in) or any user-defined type from llm-wiki.customTypes config",
|
|
426
426
|
}),
|
|
427
427
|
title: Type.String({ description: "Page title" }),
|
|
428
428
|
content: Type.Optional(Type.String({ description: "Optional initial content (otherwise uses template)" })),
|
|
@@ -442,9 +442,8 @@ export function registerWikiEnsurePage(pi, runtime) {
|
|
|
442
442
|
isError: true,
|
|
443
443
|
};
|
|
444
444
|
}
|
|
445
|
-
const
|
|
446
|
-
const
|
|
447
|
-
const folderMap = {
|
|
445
|
+
const config = loadTaskConfig(ctx.cwd);
|
|
446
|
+
const builtInFolderMap = {
|
|
448
447
|
entity: "entities",
|
|
449
448
|
concept: "concepts",
|
|
450
449
|
synthesis: "syntheses",
|
|
@@ -453,6 +452,9 @@ export function registerWikiEnsurePage(pi, runtime) {
|
|
|
453
452
|
skill: "skills",
|
|
454
453
|
case: "cases",
|
|
455
454
|
};
|
|
455
|
+
const folderMap = { ...builtInFolderMap, ...config.customTypes };
|
|
456
|
+
const type = params.type;
|
|
457
|
+
const slug = slugify(params.title);
|
|
456
458
|
const folder = folderMap[type] || "concepts";
|
|
457
459
|
const pagePath = join(paths.wiki, folder, `${slug}.md`);
|
|
458
460
|
if (existsSync(pagePath)) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, mkdirSync,
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { Type } from "typebox";
|
|
4
4
|
import { appendEvent, rebuildMetadataLight } from "./metadata.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, lstatSync, mkdirSync,
|
|
1
|
+
import { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, readlinkSync, realpathSync, renameSync, rmdirSync, writeFileSync, } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { basename, dirname, isAbsolute, join, relative, sep } from "node:path";
|
|
4
4
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, lstatSync,
|
|
1
|
+
import { existsSync, lstatSync, readdirSync, readFileSync } from "node:fs";
|
|
2
2
|
import { isAbsolute, join, relative, sep } from "node:path";
|
|
3
3
|
import { parseKnowledgeDocument, parseMarkdownFrontmatter, } from "./knowledge-document.js";
|
|
4
4
|
import { relativePhysicalPath } from "./utils.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { formatActiveModelLabel, MODEL_STATUS_KEY } from "./model-command.js";
|
|
2
2
|
import { noticesEnabled } from "./task-config.js";
|
|
3
3
|
/**
|
|
4
4
|
* Apply the two post-session-start visible status lines (issue #77,
|
package/dist/mcp/operations.js
CHANGED
|
@@ -14,7 +14,7 @@ import { saveInsight } from "../extensions/llm-wiki/lib/retro.js";
|
|
|
14
14
|
import { captureFile, captureText, captureUrl } from "../extensions/llm-wiki/lib/source-packet.js";
|
|
15
15
|
import { resolveWikilinkValidation } from "../extensions/llm-wiki/lib/task-config.js";
|
|
16
16
|
import { readJson } from "../extensions/llm-wiki/lib/utils.js";
|
|
17
|
-
import {
|
|
17
|
+
import { inspectVaultFormat, inspectWritableVault, VaultWriteError, } from "../extensions/llm-wiki/lib/vault-format.js";
|
|
18
18
|
import { getWikiStatus, searchRegistry } from "../extensions/llm-wiki/lib/wiki-service.js";
|
|
19
19
|
function projectionOutcome(projection) {
|
|
20
20
|
return projection.ok
|