@zosmaai/pi-llm-wiki 0.9.0 → 0.9.2
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/CHANGELOG.md +7 -0
- package/README.de.md +2 -2
- package/README.es.md +2 -2
- package/README.fr.md +2 -2
- package/README.hi.md +2 -2
- package/README.ja.md +2 -2
- package/README.ko.md +2 -2
- package/README.md +25 -2
- package/README.pt.md +2 -2
- package/README.ru.md +2 -2
- package/README.zh.md +2 -2
- package/docs/api.md +123 -10
- package/docs/architecture.md +38 -1
- package/docs/commands.md +21 -1
- package/extensions/llm-wiki/index.ts +80 -17
- package/extensions/llm-wiki/lib/metadata.ts +34 -1
- package/extensions/llm-wiki/lib/observation.ts +50 -10
- package/extensions/llm-wiki/lib/recall.ts +107 -8
- package/extensions/llm-wiki/lib/runtime.ts +49 -1
- package/extensions/llm-wiki/lib/task-config.ts +107 -13
- package/extensions/llm-wiki/lib/tools.ts +338 -183
- package/extensions/llm-wiki/lib/trajectories-command.ts +67 -0
- package/extensions/llm-wiki/lib/trajectory.ts +613 -0
- package/extensions/llm-wiki/lib/utils.ts +20 -3
- package/extensions/llm-wiki/lib/visible-status.ts +51 -0
- package/package.json +1 -1
- package/prompts/wiki-record.md +36 -0
- package/prompts/wiki-run.md +4 -2
- package/prompts/wiki-skills.md +26 -0
- package/skills/llm-wiki/SKILL.md +70 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
3
|
import { getAgentDir } from "@mariozechner/pi-coding-agent";
|
|
4
4
|
|
|
@@ -69,10 +69,58 @@ export interface TaskConfig {
|
|
|
69
69
|
* previews inline. Clamped to a non-negative integer.
|
|
70
70
|
*/
|
|
71
71
|
recallLinksThreshold?: number;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Max characters of a distilled `skill`/`case` body inlined directly into a
|
|
75
|
+
* recall block before truncation (recall-adherence fix). Skills/cases are
|
|
76
|
+
* meant to be APPLIED immediately, so links-first recall inlines their short
|
|
77
|
+
* body instead of a bare link the agent often skips. Set to 0 to DISABLE
|
|
78
|
+
* inlining entirely — skills/cases then fall back to the normal link/preview
|
|
79
|
+
* path (pure links-first), and no page body is read at format time. Only
|
|
80
|
+
* relevant when the trajectories feature is on (skill/case pages exist only
|
|
81
|
+
* then). Default 1600. Clamped to a non-negative integer. Mirrors the
|
|
82
|
+
* `recallLinksThreshold` knob — the other context-window lever for recall.
|
|
83
|
+
*/
|
|
84
|
+
recallSkillInlineMax?: number;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Surface wiki activity in the UI (issue #77). When enabled (the default),
|
|
88
|
+
* the status line reflects recall hits and the periodic observe/retro
|
|
89
|
+
* reminder is shown to the user (`display: true`) instead of being injected
|
|
90
|
+
* silently. Set to `false` to restore the previous quiet behavior — a static
|
|
91
|
+
* status line and a hidden (`display: false`) reminder — for users who do
|
|
92
|
+
* not want any chat-level wiki notices.
|
|
93
|
+
*/
|
|
94
|
+
notices?: boolean;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Agent-trajectory working-memory (capture → distill → recall), issue #80.
|
|
98
|
+
* OPT-IN, default OFF: only an explicit `trajectories: true` enables it.
|
|
99
|
+
* When off, the trajectory tools are never registered (see index.ts), so
|
|
100
|
+
* they cost nothing in the system prompt for the ~95% who don't use them.
|
|
101
|
+
*/
|
|
102
|
+
trajectories?: boolean;
|
|
72
103
|
}
|
|
73
104
|
|
|
74
105
|
export const TASK_DEFAULTS: TaskConfig = {};
|
|
75
106
|
|
|
107
|
+
/**
|
|
108
|
+
* Resolve whether user-facing wiki notices are enabled (issue #77). Defaults
|
|
109
|
+
* to `true`; only an explicit `notices: false` disables them.
|
|
110
|
+
*/
|
|
111
|
+
export function noticesEnabled(config: TaskConfig | undefined): boolean {
|
|
112
|
+
return config?.notices !== false;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Resolve whether agent-trajectory working-memory is enabled (issue #80).
|
|
117
|
+
* INVERSE polarity of `noticesEnabled`: defaults to `false`; only an explicit
|
|
118
|
+
* `trajectories: true` turns it on.
|
|
119
|
+
*/
|
|
120
|
+
export function trajectoriesEnabled(config: TaskConfig | undefined): boolean {
|
|
121
|
+
return config?.trajectories === true;
|
|
122
|
+
}
|
|
123
|
+
|
|
76
124
|
const SETTINGS_KEY = "llm-wiki";
|
|
77
125
|
|
|
78
126
|
function readModelSpec(value: unknown): { provider: string; id: string } | undefined {
|
|
@@ -85,9 +133,8 @@ function readModelSpec(value: unknown): { provider: string; id: string } | undef
|
|
|
85
133
|
}
|
|
86
134
|
|
|
87
135
|
function readNamespacedConfig(path: string): Partial<TaskConfig> {
|
|
88
|
-
if (!existsSync(path)) return {};
|
|
89
136
|
try {
|
|
90
|
-
const raw =
|
|
137
|
+
const raw = readSettingsObject(path);
|
|
91
138
|
const nested = raw[SETTINGS_KEY];
|
|
92
139
|
if (!nested || typeof nested !== "object") return {};
|
|
93
140
|
const section = nested as Record<string, unknown>;
|
|
@@ -115,6 +162,19 @@ function readNamespacedConfig(path: string): Partial<TaskConfig> {
|
|
|
115
162
|
if (typeof threshold === "number" && Number.isFinite(threshold)) {
|
|
116
163
|
out.recallLinksThreshold = Math.max(0, Math.floor(threshold));
|
|
117
164
|
}
|
|
165
|
+
|
|
166
|
+
const inlineMax = section.recallSkillInlineMax;
|
|
167
|
+
if (typeof inlineMax === "number" && Number.isFinite(inlineMax)) {
|
|
168
|
+
out.recallSkillInlineMax = Math.max(0, Math.floor(inlineMax));
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (typeof section.notices === "boolean") {
|
|
172
|
+
out.notices = section.notices;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (typeof section.trajectories === "boolean") {
|
|
176
|
+
out.trajectories = section.trajectories;
|
|
177
|
+
}
|
|
118
178
|
return out;
|
|
119
179
|
} catch {
|
|
120
180
|
return {};
|
|
@@ -138,6 +198,22 @@ export function parseModelRef(ref: string): { provider: string; id: string } | u
|
|
|
138
198
|
return { provider, id };
|
|
139
199
|
}
|
|
140
200
|
|
|
201
|
+
/**
|
|
202
|
+
* Read a settings JSON file as a plain object, or `{}` when it is absent or
|
|
203
|
+
* corrupt. Reads directly (no `existsSync` pre-check) so there is no
|
|
204
|
+
* check-then-use race: a missing file throws ENOENT, which the catch treats
|
|
205
|
+
* the same as an empty file.
|
|
206
|
+
*/
|
|
207
|
+
function readSettingsObject(path: string): Record<string, unknown> {
|
|
208
|
+
try {
|
|
209
|
+
const parsed = JSON.parse(readFileSync(path, "utf-8"));
|
|
210
|
+
if (parsed && typeof parsed === "object") return parsed as Record<string, unknown>;
|
|
211
|
+
} catch {
|
|
212
|
+
// Missing or corrupt settings file: start from an empty object.
|
|
213
|
+
}
|
|
214
|
+
return {};
|
|
215
|
+
}
|
|
216
|
+
|
|
141
217
|
/**
|
|
142
218
|
* Persist (or clear) the wiki background `taskModel` in the PROJECT settings
|
|
143
219
|
* file `<cwd>/.pi/settings.json` under the namespaced `llm-wiki` key (issue
|
|
@@ -151,16 +227,7 @@ export function persistTaskModel(
|
|
|
151
227
|
model: { provider: string; id: string } | undefined,
|
|
152
228
|
): void {
|
|
153
229
|
const settingsPath = join(cwd, ".pi", "settings.json");
|
|
154
|
-
|
|
155
|
-
if (existsSync(settingsPath)) {
|
|
156
|
-
try {
|
|
157
|
-
const parsed = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
158
|
-
if (parsed && typeof parsed === "object") raw = parsed as Record<string, unknown>;
|
|
159
|
-
} catch {
|
|
160
|
-
// Corrupt settings file: start from an empty object rather than throw.
|
|
161
|
-
raw = {};
|
|
162
|
-
}
|
|
163
|
-
}
|
|
230
|
+
const raw = readSettingsObject(settingsPath);
|
|
164
231
|
|
|
165
232
|
const existing = raw[SETTINGS_KEY];
|
|
166
233
|
const section: Record<string, unknown> =
|
|
@@ -178,6 +245,33 @@ export function persistTaskModel(
|
|
|
178
245
|
writeFileSync(settingsPath, `${JSON.stringify(raw, null, 2)}\n`, "utf-8");
|
|
179
246
|
}
|
|
180
247
|
|
|
248
|
+
/**
|
|
249
|
+
* Persist the agent-trajectory flag in the PROJECT settings file
|
|
250
|
+
* `<cwd>/.pi/settings.json` under the namespaced `llm-wiki` key (issue #80).
|
|
251
|
+
* Mirrors `persistTaskModel`: project settings win in `loadTaskConfig`, other
|
|
252
|
+
* keys are preserved. `true` writes `trajectories: true`; `false` removes the
|
|
253
|
+
* key (reverting to the default-off behavior).
|
|
254
|
+
*/
|
|
255
|
+
export function persistTrajectoriesEnabled(cwd: string, enabled: boolean): void {
|
|
256
|
+
const settingsPath = join(cwd, ".pi", "settings.json");
|
|
257
|
+
const raw = readSettingsObject(settingsPath);
|
|
258
|
+
|
|
259
|
+
const existing = raw[SETTINGS_KEY];
|
|
260
|
+
const section: Record<string, unknown> =
|
|
261
|
+
existing && typeof existing === "object" ? { ...(existing as Record<string, unknown>) } : {};
|
|
262
|
+
|
|
263
|
+
if (enabled) {
|
|
264
|
+
section.trajectories = true;
|
|
265
|
+
} else {
|
|
266
|
+
// biome-ignore lint/performance/noDelete: one-off settings rewrite, not a hot path; removing the key keeps the JSON clean (default is off)
|
|
267
|
+
delete section.trajectories;
|
|
268
|
+
}
|
|
269
|
+
raw[SETTINGS_KEY] = section;
|
|
270
|
+
|
|
271
|
+
mkdirSync(dirname(settingsPath), { recursive: true });
|
|
272
|
+
writeFileSync(settingsPath, `${JSON.stringify(raw, null, 2)}\n`, "utf-8");
|
|
273
|
+
}
|
|
274
|
+
|
|
181
275
|
export function loadTaskConfig(cwd: string): TaskConfig {
|
|
182
276
|
let globalPath: string;
|
|
183
277
|
try {
|