diffwiki-core 0.14.0 → 0.15.0
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/dist/bm25.cjs +6 -0
- package/dist/bm25.js +1 -1
- package/dist/chunk-6MW6KSS4.js +278 -0
- package/dist/{chunk-FTUF6IXS.js → chunk-TK2373AM.js} +6 -0
- package/dist/{chunk-7V2DIQNL.js → chunk-TXM4OGBA.js} +12 -3
- package/dist/{events-AVD3G5AX.js → events-K3MKWACA.js} +1 -1
- package/dist/frontmatter-ghMCpLNf.d.cts +585 -0
- package/dist/frontmatter-ghMCpLNf.d.ts +585 -0
- package/dist/index.cjs +303 -195
- package/dist/index.d.cts +69 -359
- package/dist/index.d.ts +69 -359
- package/dist/index.js +200 -189
- package/dist/plugin.cjs +134 -2
- package/dist/plugin.d.cts +54 -177
- package/dist/plugin.d.ts +54 -177
- package/dist/plugin.js +9 -3
- package/package.json +1 -1
- package/dist/chunk-EEETAETA.js +0 -145
package/dist/plugin.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/plugin.ts
|
|
@@ -22,9 +32,12 @@ var plugin_exports = {};
|
|
|
22
32
|
__export(plugin_exports, {
|
|
23
33
|
commandExists: () => commandExists,
|
|
24
34
|
definePlugin: () => definePlugin,
|
|
35
|
+
ensureTool: () => ensureTool,
|
|
36
|
+
parseArticle: () => parseArticle,
|
|
25
37
|
resolveDependency: () => resolveDependency,
|
|
26
38
|
runProcess: () => runProcess,
|
|
27
|
-
runProcessJson: () => runProcessJson
|
|
39
|
+
runProcessJson: () => runProcessJson,
|
|
40
|
+
stripFrontmatter: () => stripFrontmatter
|
|
28
41
|
});
|
|
29
42
|
module.exports = __toCommonJS(plugin_exports);
|
|
30
43
|
|
|
@@ -34,6 +47,71 @@ var import_node_util = require("util");
|
|
|
34
47
|
var import_node_fs = require("fs");
|
|
35
48
|
var import_node_path = require("path");
|
|
36
49
|
var import_node_url = require("url");
|
|
50
|
+
|
|
51
|
+
// src/frontmatter.ts
|
|
52
|
+
var import_gray_matter = __toESM(require("gray-matter"), 1);
|
|
53
|
+
var import_yaml = require("yaml");
|
|
54
|
+
var YAML_ENGINE = {
|
|
55
|
+
parse: (input) => {
|
|
56
|
+
const data = (0, import_yaml.parse)(input);
|
|
57
|
+
return data && typeof data === "object" ? data : {};
|
|
58
|
+
},
|
|
59
|
+
stringify: (data) => (0, import_yaml.stringify)(data)
|
|
60
|
+
};
|
|
61
|
+
var MATTER_OPTS = { engines: { yaml: YAML_ENGINE } };
|
|
62
|
+
function coerceAudience(value) {
|
|
63
|
+
return value === "private" || value === "system" ? value : "public";
|
|
64
|
+
}
|
|
65
|
+
function coerceStatus(value) {
|
|
66
|
+
return value === "draft" || value === "deprecated" ? value : "published";
|
|
67
|
+
}
|
|
68
|
+
function parseFallback(raw) {
|
|
69
|
+
const fenceRe = /^---[ \t]*\n([\s\S]*?)\n---[ \t]*\n/;
|
|
70
|
+
const fenceMatch = fenceRe.exec(raw);
|
|
71
|
+
let title = "";
|
|
72
|
+
let audience = "public";
|
|
73
|
+
let status = "published";
|
|
74
|
+
let body;
|
|
75
|
+
const clean = (s) => s.trim().replace(/^["']|["']$/g, "");
|
|
76
|
+
if (fenceMatch) {
|
|
77
|
+
const inner = fenceMatch[1];
|
|
78
|
+
const titleMatch = /^title:\s*(.+)$/m.exec(inner);
|
|
79
|
+
if (titleMatch) {
|
|
80
|
+
title = clean(titleMatch[1]);
|
|
81
|
+
}
|
|
82
|
+
const audienceMatch = /^audience:\s*(.+)$/m.exec(inner);
|
|
83
|
+
if (audienceMatch) {
|
|
84
|
+
audience = coerceAudience(clean(audienceMatch[1]));
|
|
85
|
+
}
|
|
86
|
+
const statusMatch = /^status:\s*(.+)$/m.exec(inner);
|
|
87
|
+
if (statusMatch) {
|
|
88
|
+
status = coerceStatus(clean(statusMatch[1]));
|
|
89
|
+
}
|
|
90
|
+
body = raw.slice(fenceMatch[0].length);
|
|
91
|
+
} else {
|
|
92
|
+
body = raw;
|
|
93
|
+
}
|
|
94
|
+
return { title, tags: [], audience, status, body: body.replace(/^\n+/, "") };
|
|
95
|
+
}
|
|
96
|
+
var FRONTMATTER_BLOCK_RE = /^\uFEFF?[ \t]*---\r?\n[\s\S]*?\r?\n---[ \t]*(?:\r?\n|$)/;
|
|
97
|
+
function stripFrontmatter(raw) {
|
|
98
|
+
return raw.replace(FRONTMATTER_BLOCK_RE, "");
|
|
99
|
+
}
|
|
100
|
+
function parseArticle(raw) {
|
|
101
|
+
try {
|
|
102
|
+
const { data, content } = (0, import_gray_matter.default)(raw, MATTER_OPTS);
|
|
103
|
+
const title = typeof data.title === "string" ? data.title : "";
|
|
104
|
+
const tags = Array.isArray(data.tags) ? data.tags.map((t) => String(t)) : [];
|
|
105
|
+
const created = typeof data.created === "string" ? data.created : void 0;
|
|
106
|
+
const audience = coerceAudience(data.audience);
|
|
107
|
+
const status = coerceStatus(data.status);
|
|
108
|
+
return { title, tags, created, audience, status, body: content.replace(/^\n+/, "") };
|
|
109
|
+
} catch {
|
|
110
|
+
return parseFallback(raw);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// src/plugins/sdk.ts
|
|
37
115
|
var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
|
|
38
116
|
async function runProcess(file, args, opts) {
|
|
39
117
|
const { stdout, stderr } = await execFileAsync(file, args, {
|
|
@@ -90,6 +168,57 @@ async function resolveDependency(dep, fromUrl) {
|
|
|
90
168
|
}
|
|
91
169
|
return { dependency: dep, command: null, source: "missing" };
|
|
92
170
|
}
|
|
171
|
+
async function ensureTool(spec, opts) {
|
|
172
|
+
const exists = opts?.exists ?? commandExists;
|
|
173
|
+
const run = opts?.run ?? ((file, args) => runProcess(file, args));
|
|
174
|
+
const log = opts?.log;
|
|
175
|
+
if (await exists(spec.command)) {
|
|
176
|
+
return { command: spec.command, present: true, installed: false, message: `${spec.command} present` };
|
|
177
|
+
}
|
|
178
|
+
if (!opts?.install) {
|
|
179
|
+
return {
|
|
180
|
+
command: spec.command,
|
|
181
|
+
present: false,
|
|
182
|
+
installed: false,
|
|
183
|
+
message: `${spec.command} not found \u2014 ${spec.manual}`
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
const attempts = [];
|
|
187
|
+
if (spec.mise && await exists("mise"))
|
|
188
|
+
attempts.push({ method: "mise", bin: "mise", args: ["use", "-g", spec.mise] });
|
|
189
|
+
if (spec.brew && await exists("brew")) attempts.push({ method: "brew", bin: "brew", args: ["install", spec.brew] });
|
|
190
|
+
for (const a of attempts) {
|
|
191
|
+
try {
|
|
192
|
+
log?.("info", `installing ${spec.command} via ${a.method}\u2026`);
|
|
193
|
+
await run(a.bin, a.args);
|
|
194
|
+
if (await exists(spec.command)) {
|
|
195
|
+
return {
|
|
196
|
+
command: spec.command,
|
|
197
|
+
present: true,
|
|
198
|
+
installed: true,
|
|
199
|
+
method: a.method,
|
|
200
|
+
message: `installed ${spec.command} via ${a.method}`
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
command: spec.command,
|
|
205
|
+
present: false,
|
|
206
|
+
installed: true,
|
|
207
|
+
method: a.method,
|
|
208
|
+
message: `installed ${spec.command} via ${a.method}, but it isn't on PATH yet \u2014 restart your shell (or activate ${a.method}) and retry`
|
|
209
|
+
};
|
|
210
|
+
} catch (err) {
|
|
211
|
+
log?.("warn", `${a.method} could not install ${spec.command}: ${err.message}`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
const aptHint = spec.apt ? ` (Debian/Ubuntu: sudo apt-get install -y ${spec.apt})` : "";
|
|
215
|
+
return {
|
|
216
|
+
command: spec.command,
|
|
217
|
+
present: false,
|
|
218
|
+
installed: false,
|
|
219
|
+
message: `could not auto-install ${spec.command} \u2014 ${spec.manual}${aptHint}`
|
|
220
|
+
};
|
|
221
|
+
}
|
|
93
222
|
function definePlugin(def) {
|
|
94
223
|
const { name, kind, version, capabilities, dependencies, handlers } = def;
|
|
95
224
|
const describeResult = {
|
|
@@ -169,7 +298,10 @@ function definePlugin(def) {
|
|
|
169
298
|
0 && (module.exports = {
|
|
170
299
|
commandExists,
|
|
171
300
|
definePlugin,
|
|
301
|
+
ensureTool,
|
|
302
|
+
parseArticle,
|
|
172
303
|
resolveDependency,
|
|
173
304
|
runProcess,
|
|
174
|
-
runProcessJson
|
|
305
|
+
runProcessJson,
|
|
306
|
+
stripFrontmatter
|
|
175
307
|
});
|
package/dist/plugin.d.cts
CHANGED
|
@@ -1,179 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* re-exported to plugin authors via the `diffwiki-core/plugin` subpath.
|
|
4
|
-
*
|
|
5
|
-
* @module
|
|
6
|
-
*/
|
|
7
|
-
/** Log severity levels for plugin diagnostic messages. */
|
|
8
|
-
type LogLevel = 'info' | 'warn' | 'error';
|
|
9
|
-
/** A logging function that plugins use to emit diagnostic messages to stderr. */
|
|
10
|
-
type PluginLogFn = (level: LogLevel, message: string) => void;
|
|
11
|
-
/** A wire-format collection as received in handler params. */
|
|
12
|
-
interface WireCollection {
|
|
13
|
-
name: string;
|
|
14
|
-
path: string;
|
|
15
|
-
}
|
|
16
|
-
/** Diagnostic entry returned by the health handler. */
|
|
17
|
-
interface WireDiagnostic {
|
|
18
|
-
level: 'ok' | 'warn' | 'error';
|
|
19
|
-
message: string;
|
|
20
|
-
}
|
|
21
|
-
/** Readiness details returned by the health handler. */
|
|
22
|
-
interface WireReadiness {
|
|
23
|
-
toolInstalled: boolean;
|
|
24
|
-
modelsPresent: boolean;
|
|
25
|
-
indexBuilt: boolean;
|
|
26
|
-
docsIndexed: number;
|
|
27
|
-
embeddingsPending: number;
|
|
28
|
-
firstSearchCost: 'instant' | 'model-load' | 'model-download';
|
|
29
|
-
}
|
|
30
|
-
/** A single search hit returned by the search handler. */
|
|
31
|
-
interface SearchHandlerHit {
|
|
32
|
-
collection: string;
|
|
33
|
-
relPath: string;
|
|
34
|
-
title: string;
|
|
35
|
-
snippet?: string;
|
|
36
|
-
score?: number;
|
|
37
|
-
docid?: string;
|
|
38
|
-
tags?: string[];
|
|
39
|
-
}
|
|
40
|
-
/** Result shape returned by the search handler. */
|
|
41
|
-
interface SearchHandlerResult {
|
|
42
|
-
hits: SearchHandlerHit[];
|
|
43
|
-
}
|
|
44
|
-
/** Result shape returned by the index handler. */
|
|
45
|
-
interface IndexHandlerResult {
|
|
46
|
-
indexed: number;
|
|
47
|
-
}
|
|
48
|
-
/** Result shape returned by the health handler. */
|
|
49
|
-
interface HealthHandlerResult {
|
|
50
|
-
ready: boolean;
|
|
51
|
-
readiness?: WireReadiness;
|
|
52
|
-
diagnostics: WireDiagnostic[];
|
|
53
|
-
}
|
|
54
|
-
/** Result shape returned by the setup handler. */
|
|
55
|
-
interface SetupHandlerResult {
|
|
56
|
-
ready: boolean;
|
|
57
|
-
steps?: Array<{
|
|
58
|
-
step: string;
|
|
59
|
-
ok: boolean;
|
|
60
|
-
message?: string;
|
|
61
|
-
}>;
|
|
62
|
-
}
|
|
63
|
-
/** Result shape returned by the onEvent handler. */
|
|
64
|
-
interface EventHandlerResult {
|
|
65
|
-
accepted: boolean;
|
|
66
|
-
}
|
|
67
|
-
/** Parameters passed to the search handler. */
|
|
68
|
-
interface SearchParams {
|
|
69
|
-
term: string;
|
|
70
|
-
collections: WireCollection[];
|
|
71
|
-
collection?: string;
|
|
72
|
-
type?: string;
|
|
73
|
-
limit?: number;
|
|
74
|
-
}
|
|
75
|
-
/** Parameters passed to the index handler. */
|
|
76
|
-
interface IndexParams {
|
|
77
|
-
collections: WireCollection[];
|
|
78
|
-
embed?: boolean;
|
|
79
|
-
}
|
|
80
|
-
/** Parameters passed to the setup handler. */
|
|
81
|
-
interface SetupParams {
|
|
82
|
-
collections: WireCollection[];
|
|
83
|
-
embed?: boolean;
|
|
84
|
-
prefetchModels?: boolean;
|
|
85
|
-
}
|
|
86
|
-
/** Parameters passed to the onEvent handler. */
|
|
87
|
-
interface EventParams {
|
|
88
|
-
event: string;
|
|
89
|
-
collection: WireCollection;
|
|
90
|
-
relPath?: string;
|
|
91
|
-
collections: WireCollection[];
|
|
92
|
-
}
|
|
93
|
-
/** Parameters passed to the health handler. */
|
|
94
|
-
interface HealthParams {
|
|
95
|
-
collections: WireCollection[];
|
|
96
|
-
}
|
|
97
|
-
/** Plugin capabilities advertised during describe. */
|
|
98
|
-
interface PluginCapabilities {
|
|
99
|
-
searchTypes: string[];
|
|
100
|
-
collectionFilter: boolean;
|
|
101
|
-
events: boolean;
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* An external executable a plugin needs at runtime (e.g. `qmd`, `rg`).
|
|
105
|
-
*
|
|
106
|
-
* Declaring a dependency lets the plugin resolve the binary uniformly and lets
|
|
107
|
-
* `setup`/`health` report it. When `npm` is set, the package is expected to be a
|
|
108
|
-
* regular dependency in the plugin's own `package.json`, so `diffwiki plugin
|
|
109
|
-
* install` pulls it transitively and {@link ResolvedDependency} finds its bin in
|
|
110
|
-
* the plugin's `node_modules` — no global install required.
|
|
111
|
-
*/
|
|
112
|
-
interface PluginDependency {
|
|
113
|
-
/** The executable name, e.g. `'qmd'` or `'rg'`. */
|
|
114
|
-
command: string;
|
|
115
|
-
/** npm package that provides the executable; when set, the local bin is preferred over PATH. */
|
|
116
|
-
npm?: string;
|
|
117
|
-
/** Human-facing manual install hint, shown when the dependency is unresolved. */
|
|
118
|
-
hint?: string;
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* The outcome of resolving a {@link PluginDependency}: the argv prefix to invoke
|
|
122
|
-
* it, plus where it was found. `command` is null when unresolved.
|
|
123
|
-
*/
|
|
124
|
-
interface ResolvedDependency {
|
|
125
|
-
dependency: PluginDependency;
|
|
126
|
-
/** Argv prefix to spawn the tool, or null if unresolved. */
|
|
127
|
-
command: string[] | null;
|
|
128
|
-
/** How it resolved: the npm-provided local bin, the system PATH, or nowhere. */
|
|
129
|
-
source: 'npm' | 'path' | 'missing';
|
|
130
|
-
}
|
|
131
|
-
/** The handler functions a plugin provides. */
|
|
132
|
-
interface PluginHandlers {
|
|
133
|
-
/** Handle a search request. Required for search plugins. */
|
|
134
|
-
search: (params: SearchParams, log: PluginLogFn) => Promise<SearchHandlerResult> | SearchHandlerResult;
|
|
135
|
-
/** Handle a reindex request. Optional -- defaults to `{ indexed: 0 }`. */
|
|
136
|
-
index?: (params: IndexParams, log: PluginLogFn) => Promise<IndexHandlerResult> | IndexHandlerResult;
|
|
137
|
-
/** Handle an initial setup/provisioning request. Optional -- defaults to `{ ready: true }`. */
|
|
138
|
-
setup?: (params: SetupParams, log: PluginLogFn) => Promise<SetupHandlerResult> | SetupHandlerResult;
|
|
139
|
-
/** Handle a lifecycle event (article/collection add/update/remove). Optional. */
|
|
140
|
-
onEvent?: (params: EventParams, log: PluginLogFn) => Promise<EventHandlerResult> | EventHandlerResult;
|
|
141
|
-
/** Report plugin health and readiness. Optional. */
|
|
142
|
-
health?: (params: HealthParams, log: PluginLogFn) => Promise<HealthHandlerResult> | HealthHandlerResult;
|
|
143
|
-
}
|
|
144
|
-
/** The definition object passed to `definePlugin()`. */
|
|
145
|
-
interface PluginDefinition {
|
|
146
|
-
/** Plugin name (must match the name used in `diffwiki plugin register`). */
|
|
147
|
-
name: string;
|
|
148
|
-
/** Plugin kind. Currently only `'search'` is supported. */
|
|
149
|
-
kind: 'search';
|
|
150
|
-
/** Semantic version string. */
|
|
151
|
-
version?: string;
|
|
152
|
-
/** Plugin capabilities advertised to the host. */
|
|
153
|
-
capabilities: PluginCapabilities;
|
|
154
|
-
/** External executables the plugin needs. Reported via `describe` and resolvable via {@link ResolvedDependency}. */
|
|
155
|
-
dependencies?: PluginDependency[];
|
|
156
|
-
/** Handler functions for each operation. */
|
|
157
|
-
handlers: PluginHandlers;
|
|
158
|
-
}
|
|
159
|
-
/** The object returned by `definePlugin()`. Call `.run()` to serve one request. */
|
|
160
|
-
interface DefinedPlugin {
|
|
161
|
-
/** The plugin definition. */
|
|
162
|
-
definition: PluginDefinition;
|
|
163
|
-
/**
|
|
164
|
-
* Read one JSON request from stdin, dispatch to the matching handler, write
|
|
165
|
-
* the JSON response to stdout, and exit. Exit code 0 on success, 1 on
|
|
166
|
-
* handler error. Logs go to stderr.
|
|
167
|
-
*/
|
|
168
|
-
run: () => void;
|
|
169
|
-
}
|
|
170
|
-
/** Options for `runProcess` and `runProcessJson`. */
|
|
171
|
-
interface RunProcessOptions {
|
|
172
|
-
/** Environment variables for the child process. Defaults to `process.env`. */
|
|
173
|
-
env?: NodeJS.ProcessEnv;
|
|
174
|
-
/** Timeout in milliseconds. No timeout by default. */
|
|
175
|
-
timeout?: number;
|
|
176
|
-
}
|
|
1
|
+
import { Y as PluginDefinition, Z as DefinedPlugin, _ as PluginDependency, $ as ResolvedDependency, a0 as RunProcessOptions } from './frontmatter-ghMCpLNf.cjs';
|
|
2
|
+
export { a1 as EventHandlerResult, a2 as EventParams, a3 as HealthHandlerResult, a4 as HealthParams, a5 as IndexHandlerResult, a6 as IndexParams, a7 as LogLevel, j as ParsedArticle, a8 as PluginCapabilities, a9 as PluginHandlers, aa as PluginLogFn, J as SearchExpansion, ab as SearchHandlerHit, ac as SearchHandlerResult, ad as SearchParams, ae as SetupHandlerResult, af as SetupParams, ag as WireCollection, ah as WireDiagnostic, ai as WireReadiness, U as parseArticle, X as stripFrontmatter } from './frontmatter-ghMCpLNf.cjs';
|
|
177
3
|
|
|
178
4
|
/**
|
|
179
5
|
* diffwiki plugin authoring SDK — the public surface for plugin authors, imported
|
|
@@ -207,6 +33,57 @@ declare function commandExists(name: string): Promise<boolean>;
|
|
|
207
33
|
* @param fromUrl The plugin bin's `import.meta.url`, used to anchor node resolution.
|
|
208
34
|
*/
|
|
209
35
|
declare function resolveDependency(dep: PluginDependency, fromUrl: string): Promise<ResolvedDependency>;
|
|
36
|
+
/** Per-package-manager identifiers for a tool ensureTool can install. */
|
|
37
|
+
interface ToolInstallers {
|
|
38
|
+
/** mise tool id (installed with `mise use -g`), e.g. `'fzf'` or `'npm:@tobilu/qmd'`. */
|
|
39
|
+
mise?: string;
|
|
40
|
+
/** Homebrew formula (installed with `brew install`), e.g. `'fzf'`. */
|
|
41
|
+
brew?: string;
|
|
42
|
+
/** apt package name. NOT auto-run (needs sudo) — surfaced as guidance only. */
|
|
43
|
+
apt?: string;
|
|
44
|
+
}
|
|
45
|
+
/** A tool to ensure is on PATH, with the package ids + a manual fallback hint. */
|
|
46
|
+
interface EnsureToolSpec extends ToolInstallers {
|
|
47
|
+
/** Executable checked on PATH, e.g. `'fzf'`. */
|
|
48
|
+
command: string;
|
|
49
|
+
/** Manual instruction (URL or command) shown when auto-install can't proceed. */
|
|
50
|
+
manual: string;
|
|
51
|
+
}
|
|
52
|
+
/** The outcome of an {@link ensureTool} call. */
|
|
53
|
+
interface EnsureToolResult {
|
|
54
|
+
command: string;
|
|
55
|
+
/** True if the tool is on PATH after ensureTool ran. */
|
|
56
|
+
present: boolean;
|
|
57
|
+
/** True if ensureTool installed it during this call. */
|
|
58
|
+
installed: boolean;
|
|
59
|
+
/** The manager used, when an install was attempted and succeeded. */
|
|
60
|
+
method?: 'mise' | 'brew';
|
|
61
|
+
/** A human-facing message describing the outcome. */
|
|
62
|
+
message: string;
|
|
63
|
+
}
|
|
64
|
+
/** Injectable seams for {@link ensureTool} (defaults hit the real system). */
|
|
65
|
+
interface EnsureToolOptions {
|
|
66
|
+
/** Attempt installation when the tool is missing (default: false — check only). */
|
|
67
|
+
install?: boolean;
|
|
68
|
+
/** Diagnostic sink. */
|
|
69
|
+
log?: (level: 'info' | 'warn' | 'error', message: string) => void;
|
|
70
|
+
/** Existence probe (injected in tests). Defaults to {@link commandExists}. */
|
|
71
|
+
exists?: (command: string) => Promise<boolean>;
|
|
72
|
+
/** Command runner (injected in tests). Defaults to {@link runProcess}. */
|
|
73
|
+
run?: (file: string, args: readonly string[]) => Promise<unknown>;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Ensure a system tool is on PATH, optionally installing it via a detected
|
|
77
|
+
* package manager. Detection order: **mise**, then **Homebrew**. `apt` is
|
|
78
|
+
* intentionally never auto-run (it needs `sudo`, which would hang or prompt) —
|
|
79
|
+
* it is included in the guidance message instead. Safe to call when the tool
|
|
80
|
+
* already exists (returns immediately) and never throws.
|
|
81
|
+
*
|
|
82
|
+
* Note: a tool installed via mise may not be on PATH in the current process
|
|
83
|
+
* until mise's shims are active; that case is reported as `installed:true,
|
|
84
|
+
* present:false` with a message telling the user to restart their shell.
|
|
85
|
+
*/
|
|
86
|
+
declare function ensureTool(spec: EnsureToolSpec, opts?: EnsureToolOptions): Promise<EnsureToolResult>;
|
|
210
87
|
/**
|
|
211
88
|
* Define a diffwiki plugin. The required entry point for all plugins: accepts a
|
|
212
89
|
* {@link PluginDefinition} and returns a {@link DefinedPlugin} whose `.run()`
|
|
@@ -226,4 +103,4 @@ declare function resolveDependency(dep: PluginDependency, fromUrl: string): Prom
|
|
|
226
103
|
*/
|
|
227
104
|
declare function definePlugin(def: PluginDefinition): DefinedPlugin;
|
|
228
105
|
|
|
229
|
-
export {
|
|
106
|
+
export { DefinedPlugin, type EnsureToolOptions, type EnsureToolResult, type EnsureToolSpec, PluginDefinition, PluginDependency, ResolvedDependency, RunProcessOptions, type ToolInstallers, commandExists, definePlugin, ensureTool, resolveDependency, runProcess, runProcessJson };
|
package/dist/plugin.d.ts
CHANGED
|
@@ -1,179 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* re-exported to plugin authors via the `diffwiki-core/plugin` subpath.
|
|
4
|
-
*
|
|
5
|
-
* @module
|
|
6
|
-
*/
|
|
7
|
-
/** Log severity levels for plugin diagnostic messages. */
|
|
8
|
-
type LogLevel = 'info' | 'warn' | 'error';
|
|
9
|
-
/** A logging function that plugins use to emit diagnostic messages to stderr. */
|
|
10
|
-
type PluginLogFn = (level: LogLevel, message: string) => void;
|
|
11
|
-
/** A wire-format collection as received in handler params. */
|
|
12
|
-
interface WireCollection {
|
|
13
|
-
name: string;
|
|
14
|
-
path: string;
|
|
15
|
-
}
|
|
16
|
-
/** Diagnostic entry returned by the health handler. */
|
|
17
|
-
interface WireDiagnostic {
|
|
18
|
-
level: 'ok' | 'warn' | 'error';
|
|
19
|
-
message: string;
|
|
20
|
-
}
|
|
21
|
-
/** Readiness details returned by the health handler. */
|
|
22
|
-
interface WireReadiness {
|
|
23
|
-
toolInstalled: boolean;
|
|
24
|
-
modelsPresent: boolean;
|
|
25
|
-
indexBuilt: boolean;
|
|
26
|
-
docsIndexed: number;
|
|
27
|
-
embeddingsPending: number;
|
|
28
|
-
firstSearchCost: 'instant' | 'model-load' | 'model-download';
|
|
29
|
-
}
|
|
30
|
-
/** A single search hit returned by the search handler. */
|
|
31
|
-
interface SearchHandlerHit {
|
|
32
|
-
collection: string;
|
|
33
|
-
relPath: string;
|
|
34
|
-
title: string;
|
|
35
|
-
snippet?: string;
|
|
36
|
-
score?: number;
|
|
37
|
-
docid?: string;
|
|
38
|
-
tags?: string[];
|
|
39
|
-
}
|
|
40
|
-
/** Result shape returned by the search handler. */
|
|
41
|
-
interface SearchHandlerResult {
|
|
42
|
-
hits: SearchHandlerHit[];
|
|
43
|
-
}
|
|
44
|
-
/** Result shape returned by the index handler. */
|
|
45
|
-
interface IndexHandlerResult {
|
|
46
|
-
indexed: number;
|
|
47
|
-
}
|
|
48
|
-
/** Result shape returned by the health handler. */
|
|
49
|
-
interface HealthHandlerResult {
|
|
50
|
-
ready: boolean;
|
|
51
|
-
readiness?: WireReadiness;
|
|
52
|
-
diagnostics: WireDiagnostic[];
|
|
53
|
-
}
|
|
54
|
-
/** Result shape returned by the setup handler. */
|
|
55
|
-
interface SetupHandlerResult {
|
|
56
|
-
ready: boolean;
|
|
57
|
-
steps?: Array<{
|
|
58
|
-
step: string;
|
|
59
|
-
ok: boolean;
|
|
60
|
-
message?: string;
|
|
61
|
-
}>;
|
|
62
|
-
}
|
|
63
|
-
/** Result shape returned by the onEvent handler. */
|
|
64
|
-
interface EventHandlerResult {
|
|
65
|
-
accepted: boolean;
|
|
66
|
-
}
|
|
67
|
-
/** Parameters passed to the search handler. */
|
|
68
|
-
interface SearchParams {
|
|
69
|
-
term: string;
|
|
70
|
-
collections: WireCollection[];
|
|
71
|
-
collection?: string;
|
|
72
|
-
type?: string;
|
|
73
|
-
limit?: number;
|
|
74
|
-
}
|
|
75
|
-
/** Parameters passed to the index handler. */
|
|
76
|
-
interface IndexParams {
|
|
77
|
-
collections: WireCollection[];
|
|
78
|
-
embed?: boolean;
|
|
79
|
-
}
|
|
80
|
-
/** Parameters passed to the setup handler. */
|
|
81
|
-
interface SetupParams {
|
|
82
|
-
collections: WireCollection[];
|
|
83
|
-
embed?: boolean;
|
|
84
|
-
prefetchModels?: boolean;
|
|
85
|
-
}
|
|
86
|
-
/** Parameters passed to the onEvent handler. */
|
|
87
|
-
interface EventParams {
|
|
88
|
-
event: string;
|
|
89
|
-
collection: WireCollection;
|
|
90
|
-
relPath?: string;
|
|
91
|
-
collections: WireCollection[];
|
|
92
|
-
}
|
|
93
|
-
/** Parameters passed to the health handler. */
|
|
94
|
-
interface HealthParams {
|
|
95
|
-
collections: WireCollection[];
|
|
96
|
-
}
|
|
97
|
-
/** Plugin capabilities advertised during describe. */
|
|
98
|
-
interface PluginCapabilities {
|
|
99
|
-
searchTypes: string[];
|
|
100
|
-
collectionFilter: boolean;
|
|
101
|
-
events: boolean;
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* An external executable a plugin needs at runtime (e.g. `qmd`, `rg`).
|
|
105
|
-
*
|
|
106
|
-
* Declaring a dependency lets the plugin resolve the binary uniformly and lets
|
|
107
|
-
* `setup`/`health` report it. When `npm` is set, the package is expected to be a
|
|
108
|
-
* regular dependency in the plugin's own `package.json`, so `diffwiki plugin
|
|
109
|
-
* install` pulls it transitively and {@link ResolvedDependency} finds its bin in
|
|
110
|
-
* the plugin's `node_modules` — no global install required.
|
|
111
|
-
*/
|
|
112
|
-
interface PluginDependency {
|
|
113
|
-
/** The executable name, e.g. `'qmd'` or `'rg'`. */
|
|
114
|
-
command: string;
|
|
115
|
-
/** npm package that provides the executable; when set, the local bin is preferred over PATH. */
|
|
116
|
-
npm?: string;
|
|
117
|
-
/** Human-facing manual install hint, shown when the dependency is unresolved. */
|
|
118
|
-
hint?: string;
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* The outcome of resolving a {@link PluginDependency}: the argv prefix to invoke
|
|
122
|
-
* it, plus where it was found. `command` is null when unresolved.
|
|
123
|
-
*/
|
|
124
|
-
interface ResolvedDependency {
|
|
125
|
-
dependency: PluginDependency;
|
|
126
|
-
/** Argv prefix to spawn the tool, or null if unresolved. */
|
|
127
|
-
command: string[] | null;
|
|
128
|
-
/** How it resolved: the npm-provided local bin, the system PATH, or nowhere. */
|
|
129
|
-
source: 'npm' | 'path' | 'missing';
|
|
130
|
-
}
|
|
131
|
-
/** The handler functions a plugin provides. */
|
|
132
|
-
interface PluginHandlers {
|
|
133
|
-
/** Handle a search request. Required for search plugins. */
|
|
134
|
-
search: (params: SearchParams, log: PluginLogFn) => Promise<SearchHandlerResult> | SearchHandlerResult;
|
|
135
|
-
/** Handle a reindex request. Optional -- defaults to `{ indexed: 0 }`. */
|
|
136
|
-
index?: (params: IndexParams, log: PluginLogFn) => Promise<IndexHandlerResult> | IndexHandlerResult;
|
|
137
|
-
/** Handle an initial setup/provisioning request. Optional -- defaults to `{ ready: true }`. */
|
|
138
|
-
setup?: (params: SetupParams, log: PluginLogFn) => Promise<SetupHandlerResult> | SetupHandlerResult;
|
|
139
|
-
/** Handle a lifecycle event (article/collection add/update/remove). Optional. */
|
|
140
|
-
onEvent?: (params: EventParams, log: PluginLogFn) => Promise<EventHandlerResult> | EventHandlerResult;
|
|
141
|
-
/** Report plugin health and readiness. Optional. */
|
|
142
|
-
health?: (params: HealthParams, log: PluginLogFn) => Promise<HealthHandlerResult> | HealthHandlerResult;
|
|
143
|
-
}
|
|
144
|
-
/** The definition object passed to `definePlugin()`. */
|
|
145
|
-
interface PluginDefinition {
|
|
146
|
-
/** Plugin name (must match the name used in `diffwiki plugin register`). */
|
|
147
|
-
name: string;
|
|
148
|
-
/** Plugin kind. Currently only `'search'` is supported. */
|
|
149
|
-
kind: 'search';
|
|
150
|
-
/** Semantic version string. */
|
|
151
|
-
version?: string;
|
|
152
|
-
/** Plugin capabilities advertised to the host. */
|
|
153
|
-
capabilities: PluginCapabilities;
|
|
154
|
-
/** External executables the plugin needs. Reported via `describe` and resolvable via {@link ResolvedDependency}. */
|
|
155
|
-
dependencies?: PluginDependency[];
|
|
156
|
-
/** Handler functions for each operation. */
|
|
157
|
-
handlers: PluginHandlers;
|
|
158
|
-
}
|
|
159
|
-
/** The object returned by `definePlugin()`. Call `.run()` to serve one request. */
|
|
160
|
-
interface DefinedPlugin {
|
|
161
|
-
/** The plugin definition. */
|
|
162
|
-
definition: PluginDefinition;
|
|
163
|
-
/**
|
|
164
|
-
* Read one JSON request from stdin, dispatch to the matching handler, write
|
|
165
|
-
* the JSON response to stdout, and exit. Exit code 0 on success, 1 on
|
|
166
|
-
* handler error. Logs go to stderr.
|
|
167
|
-
*/
|
|
168
|
-
run: () => void;
|
|
169
|
-
}
|
|
170
|
-
/** Options for `runProcess` and `runProcessJson`. */
|
|
171
|
-
interface RunProcessOptions {
|
|
172
|
-
/** Environment variables for the child process. Defaults to `process.env`. */
|
|
173
|
-
env?: NodeJS.ProcessEnv;
|
|
174
|
-
/** Timeout in milliseconds. No timeout by default. */
|
|
175
|
-
timeout?: number;
|
|
176
|
-
}
|
|
1
|
+
import { Y as PluginDefinition, Z as DefinedPlugin, _ as PluginDependency, $ as ResolvedDependency, a0 as RunProcessOptions } from './frontmatter-ghMCpLNf.js';
|
|
2
|
+
export { a1 as EventHandlerResult, a2 as EventParams, a3 as HealthHandlerResult, a4 as HealthParams, a5 as IndexHandlerResult, a6 as IndexParams, a7 as LogLevel, j as ParsedArticle, a8 as PluginCapabilities, a9 as PluginHandlers, aa as PluginLogFn, J as SearchExpansion, ab as SearchHandlerHit, ac as SearchHandlerResult, ad as SearchParams, ae as SetupHandlerResult, af as SetupParams, ag as WireCollection, ah as WireDiagnostic, ai as WireReadiness, U as parseArticle, X as stripFrontmatter } from './frontmatter-ghMCpLNf.js';
|
|
177
3
|
|
|
178
4
|
/**
|
|
179
5
|
* diffwiki plugin authoring SDK — the public surface for plugin authors, imported
|
|
@@ -207,6 +33,57 @@ declare function commandExists(name: string): Promise<boolean>;
|
|
|
207
33
|
* @param fromUrl The plugin bin's `import.meta.url`, used to anchor node resolution.
|
|
208
34
|
*/
|
|
209
35
|
declare function resolveDependency(dep: PluginDependency, fromUrl: string): Promise<ResolvedDependency>;
|
|
36
|
+
/** Per-package-manager identifiers for a tool ensureTool can install. */
|
|
37
|
+
interface ToolInstallers {
|
|
38
|
+
/** mise tool id (installed with `mise use -g`), e.g. `'fzf'` or `'npm:@tobilu/qmd'`. */
|
|
39
|
+
mise?: string;
|
|
40
|
+
/** Homebrew formula (installed with `brew install`), e.g. `'fzf'`. */
|
|
41
|
+
brew?: string;
|
|
42
|
+
/** apt package name. NOT auto-run (needs sudo) — surfaced as guidance only. */
|
|
43
|
+
apt?: string;
|
|
44
|
+
}
|
|
45
|
+
/** A tool to ensure is on PATH, with the package ids + a manual fallback hint. */
|
|
46
|
+
interface EnsureToolSpec extends ToolInstallers {
|
|
47
|
+
/** Executable checked on PATH, e.g. `'fzf'`. */
|
|
48
|
+
command: string;
|
|
49
|
+
/** Manual instruction (URL or command) shown when auto-install can't proceed. */
|
|
50
|
+
manual: string;
|
|
51
|
+
}
|
|
52
|
+
/** The outcome of an {@link ensureTool} call. */
|
|
53
|
+
interface EnsureToolResult {
|
|
54
|
+
command: string;
|
|
55
|
+
/** True if the tool is on PATH after ensureTool ran. */
|
|
56
|
+
present: boolean;
|
|
57
|
+
/** True if ensureTool installed it during this call. */
|
|
58
|
+
installed: boolean;
|
|
59
|
+
/** The manager used, when an install was attempted and succeeded. */
|
|
60
|
+
method?: 'mise' | 'brew';
|
|
61
|
+
/** A human-facing message describing the outcome. */
|
|
62
|
+
message: string;
|
|
63
|
+
}
|
|
64
|
+
/** Injectable seams for {@link ensureTool} (defaults hit the real system). */
|
|
65
|
+
interface EnsureToolOptions {
|
|
66
|
+
/** Attempt installation when the tool is missing (default: false — check only). */
|
|
67
|
+
install?: boolean;
|
|
68
|
+
/** Diagnostic sink. */
|
|
69
|
+
log?: (level: 'info' | 'warn' | 'error', message: string) => void;
|
|
70
|
+
/** Existence probe (injected in tests). Defaults to {@link commandExists}. */
|
|
71
|
+
exists?: (command: string) => Promise<boolean>;
|
|
72
|
+
/** Command runner (injected in tests). Defaults to {@link runProcess}. */
|
|
73
|
+
run?: (file: string, args: readonly string[]) => Promise<unknown>;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Ensure a system tool is on PATH, optionally installing it via a detected
|
|
77
|
+
* package manager. Detection order: **mise**, then **Homebrew**. `apt` is
|
|
78
|
+
* intentionally never auto-run (it needs `sudo`, which would hang or prompt) —
|
|
79
|
+
* it is included in the guidance message instead. Safe to call when the tool
|
|
80
|
+
* already exists (returns immediately) and never throws.
|
|
81
|
+
*
|
|
82
|
+
* Note: a tool installed via mise may not be on PATH in the current process
|
|
83
|
+
* until mise's shims are active; that case is reported as `installed:true,
|
|
84
|
+
* present:false` with a message telling the user to restart their shell.
|
|
85
|
+
*/
|
|
86
|
+
declare function ensureTool(spec: EnsureToolSpec, opts?: EnsureToolOptions): Promise<EnsureToolResult>;
|
|
210
87
|
/**
|
|
211
88
|
* Define a diffwiki plugin. The required entry point for all plugins: accepts a
|
|
212
89
|
* {@link PluginDefinition} and returns a {@link DefinedPlugin} whose `.run()`
|
|
@@ -226,4 +103,4 @@ declare function resolveDependency(dep: PluginDependency, fromUrl: string): Prom
|
|
|
226
103
|
*/
|
|
227
104
|
declare function definePlugin(def: PluginDefinition): DefinedPlugin;
|
|
228
105
|
|
|
229
|
-
export {
|
|
106
|
+
export { DefinedPlugin, type EnsureToolOptions, type EnsureToolResult, type EnsureToolSpec, PluginDefinition, PluginDependency, ResolvedDependency, RunProcessOptions, type ToolInstallers, commandExists, definePlugin, ensureTool, resolveDependency, runProcess, runProcessJson };
|