pantrybase 0.0.0-stage → 0.2.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/.claude-plugin/marketplace.json +12 -0
- package/.claude-plugin/plugin.json +27 -0
- package/LICENSE +21 -0
- package/README.md +153 -2
- package/bin/_resolve.sh +38 -0
- package/bin/pantrybase +20 -0
- package/bin/pb-server +13 -0
- package/dist/chunk-QUWSBZ2V.js +3429 -0
- package/dist/cli.js +441 -0
- package/dist/server.js +915 -0
- package/dist/web/assets/graph-qSs25SSD.js +3225 -0
- package/dist/web/assets/index-Dsc3USAJ.css +1 -0
- package/dist/web/assets/index-lHc1E7AV.js +1 -0
- package/dist/web/index.html +14 -0
- package/package.json +85 -4
- package/providers/generic/guide.md +13 -0
- package/providers/generic/profile.yaml +17 -0
- package/providers/ucook/guide.md +62 -0
- package/providers/ucook/profile.yaml +62 -0
- package/seed/ingredients.yaml +194 -0
- package/seed/vocabulary.yaml +277 -0
- package/skills/cook/SKILL.md +28 -0
- package/skills/ingest/SKILL.md +41 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Embedder,
|
|
3
|
+
MODEL_ID,
|
|
4
|
+
dataPaths,
|
|
5
|
+
homeDir,
|
|
6
|
+
log,
|
|
7
|
+
modelsDir,
|
|
8
|
+
openContext,
|
|
9
|
+
packageRoot,
|
|
10
|
+
packageVersion,
|
|
11
|
+
reconcile,
|
|
12
|
+
resolveProjectRoot,
|
|
13
|
+
searchRecipes,
|
|
14
|
+
startUiServer
|
|
15
|
+
} from "./chunk-QUWSBZ2V.js";
|
|
16
|
+
|
|
17
|
+
// src/cli.ts
|
|
18
|
+
import { spawn } from "child_process";
|
|
19
|
+
|
|
20
|
+
// src/install/install.ts
|
|
21
|
+
import fs from "fs";
|
|
22
|
+
import path from "path";
|
|
23
|
+
|
|
24
|
+
// src/install/run.ts
|
|
25
|
+
import { spawnSync } from "child_process";
|
|
26
|
+
function run(cmd, args, opts = {}) {
|
|
27
|
+
const r = spawnSync(cmd, args, {
|
|
28
|
+
cwd: opts.cwd,
|
|
29
|
+
env: { ...process.env, ...opts.env },
|
|
30
|
+
encoding: "utf8",
|
|
31
|
+
timeout: opts.timeoutMs ?? 10 * 6e4,
|
|
32
|
+
maxBuffer: 64 * 1024 * 1024
|
|
33
|
+
});
|
|
34
|
+
return {
|
|
35
|
+
ok: r.status === 0 && !r.error,
|
|
36
|
+
code: r.status,
|
|
37
|
+
stdout: r.stdout ?? "",
|
|
38
|
+
stderr: r.error ? String(r.error) : r.stderr ?? ""
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function tail(s, n = 400) {
|
|
42
|
+
const t = s.trim();
|
|
43
|
+
return t.length > n ? `\u2026${t.slice(-n)}` : t;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// src/install/claude.ts
|
|
47
|
+
var PLUGIN_ID = "pantrybase@pantrybase";
|
|
48
|
+
var MARKETPLACE = "pantrybase";
|
|
49
|
+
function json(args) {
|
|
50
|
+
const r = run("claude", args, { timeoutMs: 6e4 });
|
|
51
|
+
if (!r.ok) return void 0;
|
|
52
|
+
try {
|
|
53
|
+
return JSON.parse(r.stdout);
|
|
54
|
+
} catch {
|
|
55
|
+
return void 0;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function claudeVersion() {
|
|
59
|
+
const r = run("claude", ["--version"], { timeoutMs: 2e4 });
|
|
60
|
+
return r.ok ? r.stdout.trim() : null;
|
|
61
|
+
}
|
|
62
|
+
function registeredPlugin() {
|
|
63
|
+
return json(["plugin", "list", "--json"])?.find((p) => p.id === PLUGIN_ID);
|
|
64
|
+
}
|
|
65
|
+
function registeredMarketplace() {
|
|
66
|
+
return json(["plugin", "marketplace", "list", "--json"])?.find(
|
|
67
|
+
(m) => m.name === MARKETPLACE
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
function registerPlugin(stableRoot) {
|
|
71
|
+
const steps = [];
|
|
72
|
+
if (!claudeVersion()) {
|
|
73
|
+
return [
|
|
74
|
+
{
|
|
75
|
+
step: "claude CLI",
|
|
76
|
+
ok: false,
|
|
77
|
+
detail: "`claude` not found on PATH; install Claude Code, then re-run `pantrybase install`"
|
|
78
|
+
}
|
|
79
|
+
];
|
|
80
|
+
}
|
|
81
|
+
const market = registeredMarketplace();
|
|
82
|
+
if (market && (market.path ?? market.installLocation) !== stableRoot) {
|
|
83
|
+
run("claude", ["plugin", "marketplace", "remove", MARKETPLACE], { timeoutMs: 6e4 });
|
|
84
|
+
}
|
|
85
|
+
const again = market && (market.path ?? market.installLocation) === stableRoot;
|
|
86
|
+
const m = again ? run("claude", ["plugin", "marketplace", "update", MARKETPLACE], { timeoutMs: 12e4 }) : run("claude", ["plugin", "marketplace", "add", stableRoot], { timeoutMs: 12e4 });
|
|
87
|
+
steps.push({
|
|
88
|
+
step: again ? "marketplace update" : "marketplace add",
|
|
89
|
+
ok: m.ok,
|
|
90
|
+
detail: m.ok ? stableRoot : tail(m.stderr || m.stdout)
|
|
91
|
+
});
|
|
92
|
+
if (!m.ok) return steps;
|
|
93
|
+
const installed = registeredPlugin();
|
|
94
|
+
const p = installed ? run("claude", ["plugin", "update", PLUGIN_ID, "--scope", "user"], { timeoutMs: 12e4 }) : run("claude", ["plugin", "install", PLUGIN_ID, "--scope", "user"], { timeoutMs: 12e4 });
|
|
95
|
+
steps.push({
|
|
96
|
+
step: installed ? "plugin update" : "plugin install",
|
|
97
|
+
ok: p.ok,
|
|
98
|
+
detail: p.ok ? `${PLUGIN_ID} (user scope)` : tail(p.stderr || p.stdout)
|
|
99
|
+
});
|
|
100
|
+
return steps;
|
|
101
|
+
}
|
|
102
|
+
function unregisterPlugin() {
|
|
103
|
+
const steps = [];
|
|
104
|
+
if (registeredPlugin()) {
|
|
105
|
+
const u = run("claude", ["plugin", "uninstall", PLUGIN_ID, "--scope", "user"], {
|
|
106
|
+
timeoutMs: 12e4
|
|
107
|
+
});
|
|
108
|
+
steps.push({
|
|
109
|
+
step: "plugin uninstall",
|
|
110
|
+
ok: u.ok,
|
|
111
|
+
detail: u.ok ? PLUGIN_ID : tail(u.stderr || u.stdout)
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
if (registeredMarketplace()) {
|
|
115
|
+
const r = run("claude", ["plugin", "marketplace", "remove", MARKETPLACE], {
|
|
116
|
+
timeoutMs: 6e4
|
|
117
|
+
});
|
|
118
|
+
steps.push({
|
|
119
|
+
step: "marketplace remove",
|
|
120
|
+
ok: r.ok,
|
|
121
|
+
detail: r.ok ? MARKETPLACE : tail(r.stderr || r.stdout)
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
return steps;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// src/install/install.ts
|
|
128
|
+
function readJson(file) {
|
|
129
|
+
try {
|
|
130
|
+
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
131
|
+
} catch {
|
|
132
|
+
return void 0;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function installRecord() {
|
|
136
|
+
return readJson(path.join(homeDir(), "install.json"));
|
|
137
|
+
}
|
|
138
|
+
function materialize(from) {
|
|
139
|
+
const home = homeDir();
|
|
140
|
+
const tmp = path.join(home, "tmp");
|
|
141
|
+
const pluginDir = path.join(home, "plugin");
|
|
142
|
+
fs.mkdirSync(tmp, { recursive: true });
|
|
143
|
+
fs.mkdirSync(pluginDir, { recursive: true });
|
|
144
|
+
const steps = [];
|
|
145
|
+
const isDev = fs.existsSync(path.join(from, "src")) && fs.existsSync(path.join(from, "node_modules", ".bin", "tsup"));
|
|
146
|
+
for (const old of fs.readdirSync(tmp)) if (old.endsWith(".tgz")) fs.rmSync(path.join(tmp, old));
|
|
147
|
+
const pack = run(
|
|
148
|
+
"npm",
|
|
149
|
+
["pack", from, "--pack-destination", tmp, "--json", ...isDev ? [] : ["--ignore-scripts"]],
|
|
150
|
+
{
|
|
151
|
+
cwd: from
|
|
152
|
+
}
|
|
153
|
+
);
|
|
154
|
+
if (!pack.ok) throw new Error(`npm pack failed: ${tail(pack.stderr || pack.stdout)}`);
|
|
155
|
+
const packed = JSON.parse(pack.stdout.slice(pack.stdout.indexOf("[")))[0];
|
|
156
|
+
if (!packed) throw new Error("npm pack produced no tarball");
|
|
157
|
+
steps.push({
|
|
158
|
+
step: "pack",
|
|
159
|
+
ok: true,
|
|
160
|
+
detail: `${packed.filename}${isDev ? " (built from source)" : ""}`
|
|
161
|
+
});
|
|
162
|
+
fs.writeFileSync(
|
|
163
|
+
path.join(pluginDir, "package.json"),
|
|
164
|
+
`${JSON.stringify({ private: true, dependencies: { pantrybase: `file:../tmp/${packed.filename}` } }, null, 2)}
|
|
165
|
+
`
|
|
166
|
+
);
|
|
167
|
+
fs.rmSync(path.join(pluginDir, "node_modules", "pantrybase"), { recursive: true, force: true });
|
|
168
|
+
fs.rmSync(path.join(pluginDir, "package-lock.json"), { force: true });
|
|
169
|
+
const inst = run("npm", ["install", "--omit=dev", "--no-audit", "--no-fund"], { cwd: pluginDir });
|
|
170
|
+
if (!inst.ok) throw new Error(`npm install failed: ${tail(inst.stderr || inst.stdout)}`);
|
|
171
|
+
const stableRoot = path.join(pluginDir, "node_modules", "pantrybase");
|
|
172
|
+
const fresh = path.join(from, "dist", "server.js");
|
|
173
|
+
const installed = path.join(stableRoot, "dist", "server.js");
|
|
174
|
+
if (isDev && fs.existsSync(fresh) && fs.readFileSync(fresh, "utf8") !== fs.readFileSync(installed, "utf8")) {
|
|
175
|
+
throw new Error(`installed copy at ${stableRoot} does not match the freshly built package`);
|
|
176
|
+
}
|
|
177
|
+
steps.push({ step: "install dependencies", ok: true, detail: stableRoot });
|
|
178
|
+
return { stableRoot, version: packed.version, steps };
|
|
179
|
+
}
|
|
180
|
+
function smokeTest(stableRoot, node = process.execPath) {
|
|
181
|
+
const native = run(
|
|
182
|
+
node,
|
|
183
|
+
[
|
|
184
|
+
"-e",
|
|
185
|
+
`const r=require('node:module').createRequire(${JSON.stringify(path.join(stableRoot, "package.json"))});const D=r('better-sqlite3');const v=r('sqlite-vec');const db=new D(':memory:');v.load(db);db.exec("create virtual table t using fts5(x, tokenize='trigram')");const s=r('sharp');console.log(JSON.stringify({sqlite:db.prepare('select sqlite_version() v').get().v,vec:db.prepare('select vec_version() v').get().v,vips:s.versions.vips}))`
|
|
186
|
+
],
|
|
187
|
+
{ timeoutMs: 6e4 }
|
|
188
|
+
);
|
|
189
|
+
const probe = run(node, [path.join(stableRoot, "dist", "server.js"), "--probe"], {
|
|
190
|
+
timeoutMs: 6e4
|
|
191
|
+
});
|
|
192
|
+
let tools = 0;
|
|
193
|
+
try {
|
|
194
|
+
tools = JSON.parse(probe.stdout).tools.length;
|
|
195
|
+
} catch {
|
|
196
|
+
}
|
|
197
|
+
return [
|
|
198
|
+
{
|
|
199
|
+
step: "native modules",
|
|
200
|
+
ok: native.ok,
|
|
201
|
+
detail: native.ok ? native.stdout.trim() : tail(native.stderr)
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
step: "MCP server probe",
|
|
205
|
+
ok: probe.ok && tools > 0,
|
|
206
|
+
detail: probe.ok ? `${tools} tools` : tail(probe.stderr)
|
|
207
|
+
}
|
|
208
|
+
];
|
|
209
|
+
}
|
|
210
|
+
function modelCached() {
|
|
211
|
+
return fs.existsSync(path.join(modelsDir(), ...MODEL_ID.split("/")));
|
|
212
|
+
}
|
|
213
|
+
function warmModel(stableRoot, node = process.execPath) {
|
|
214
|
+
if (modelCached()) return { step: "embedding model", ok: true, detail: `${MODEL_ID} (cached)` };
|
|
215
|
+
const r = run(node, [path.join(stableRoot, "dist", "cli.js"), "warm-model"], {
|
|
216
|
+
timeoutMs: 20 * 6e4
|
|
217
|
+
});
|
|
218
|
+
return {
|
|
219
|
+
step: "embedding model",
|
|
220
|
+
ok: r.ok,
|
|
221
|
+
detail: r.ok ? `${MODEL_ID} downloaded` : tail(r.stderr || r.stdout)
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
function install(opts = {}) {
|
|
225
|
+
const from = path.resolve(opts.from ?? packageRoot);
|
|
226
|
+
const home = homeDir();
|
|
227
|
+
const node = process.execPath;
|
|
228
|
+
const { stableRoot, version, steps } = materialize(from);
|
|
229
|
+
fs.writeFileSync(path.join(home, "node-path"), node);
|
|
230
|
+
fs.writeFileSync(path.join(home, "root-path"), stableRoot);
|
|
231
|
+
steps.push({ step: "pin node", ok: true, detail: `${node} (${process.version})` });
|
|
232
|
+
steps.push(...smokeTest(stableRoot, node));
|
|
233
|
+
if (opts.model !== false) steps.push(warmModel(stableRoot, node));
|
|
234
|
+
let registered = false;
|
|
235
|
+
if (opts.register !== false) {
|
|
236
|
+
const reg = registerPlugin(stableRoot);
|
|
237
|
+
steps.push(...reg);
|
|
238
|
+
registered = reg.length > 0 && reg.every((s) => s.ok);
|
|
239
|
+
}
|
|
240
|
+
const record = {
|
|
241
|
+
version,
|
|
242
|
+
node,
|
|
243
|
+
stableRoot,
|
|
244
|
+
from,
|
|
245
|
+
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
246
|
+
registered
|
|
247
|
+
};
|
|
248
|
+
fs.writeFileSync(path.join(home, "install.json"), `${JSON.stringify(record, null, 2)}
|
|
249
|
+
`);
|
|
250
|
+
return { ok: steps.every((s) => s.ok), steps };
|
|
251
|
+
}
|
|
252
|
+
function uninstall(opts = {}) {
|
|
253
|
+
const home = homeDir();
|
|
254
|
+
const steps = unregisterPlugin();
|
|
255
|
+
for (const f of ["plugin", "tmp", "node-path", "root-path", "install.json", "compile-cache"]) {
|
|
256
|
+
fs.rmSync(path.join(home, f), { recursive: true, force: true });
|
|
257
|
+
}
|
|
258
|
+
steps.push({ step: "remove stable copy", ok: true, detail: path.join(home, "plugin") });
|
|
259
|
+
if (opts.purge) {
|
|
260
|
+
fs.rmSync(modelsDir(), { recursive: true, force: true });
|
|
261
|
+
steps.push({ step: "remove model cache", ok: true, detail: modelsDir() });
|
|
262
|
+
}
|
|
263
|
+
return steps;
|
|
264
|
+
}
|
|
265
|
+
function doctor(projectRoot, dataDir) {
|
|
266
|
+
const rec = installRecord();
|
|
267
|
+
const out = [];
|
|
268
|
+
const [major = 0, minor = 0] = process.versions.node.split(".").map(Number);
|
|
269
|
+
out.push({
|
|
270
|
+
step: "node",
|
|
271
|
+
ok: major > 22 || major === 22 && minor >= 12,
|
|
272
|
+
detail: `${process.version} at ${process.execPath}${rec && rec.node !== process.execPath ? ` (pinned: ${rec.node})` : ""}`
|
|
273
|
+
});
|
|
274
|
+
out.push({
|
|
275
|
+
step: "installed copy",
|
|
276
|
+
ok: !!rec && fs.existsSync(path.join(rec.stableRoot, "dist", "server.js")),
|
|
277
|
+
detail: rec ? `${rec.version} at ${rec.stableRoot}` : "not installed \u2014 run `npx pantrybase install`"
|
|
278
|
+
});
|
|
279
|
+
if (rec)
|
|
280
|
+
out.push(...smokeTest(rec.stableRoot, fs.existsSync(rec.node) ? rec.node : process.execPath));
|
|
281
|
+
out.push({
|
|
282
|
+
step: "embedding model",
|
|
283
|
+
ok: modelCached(),
|
|
284
|
+
detail: modelCached() ? `${MODEL_ID} in ${modelsDir()}` : "not downloaded yet (first search will fetch ~34 MB)"
|
|
285
|
+
});
|
|
286
|
+
const cv = claudeVersion();
|
|
287
|
+
out.push({ step: "claude CLI", ok: !!cv, detail: cv ?? "not found on PATH" });
|
|
288
|
+
if (cv) {
|
|
289
|
+
const p = registeredPlugin();
|
|
290
|
+
const m = registeredMarketplace();
|
|
291
|
+
out.push({
|
|
292
|
+
step: "plugin registered",
|
|
293
|
+
ok: !!p?.enabled,
|
|
294
|
+
detail: p ? `${PLUGIN_ID} ${p.version ?? ""} ${p.enabled ? "enabled" : "DISABLED"}, read from ${p.readFromFolder ?? m?.path ?? "?"}` : "not installed \u2014 run `npx pantrybase install`"
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
const recipes = fs.existsSync(path.join(dataDir, "recipes")) ? fs.readdirSync(path.join(dataDir, "recipes")).filter((f) => f.endsWith(".md")).length : 0;
|
|
298
|
+
out.push({
|
|
299
|
+
step: "project data",
|
|
300
|
+
ok: true,
|
|
301
|
+
detail: fs.existsSync(dataDir) ? `${dataDir} (${recipes} recipes)` : `none yet in ${projectRoot}; created on first use`
|
|
302
|
+
});
|
|
303
|
+
return out;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// src/cli.ts
|
|
307
|
+
var pkg = { version: packageVersion() };
|
|
308
|
+
var USAGE = `pantrybase ${pkg.version}
|
|
309
|
+
|
|
310
|
+
Setup
|
|
311
|
+
pantrybase install [--no-model] [--no-register]
|
|
312
|
+
install the Claude Code plugin (stable copy in ~/.pantrybase,
|
|
313
|
+
native modules checked, embedding model downloaded, plugin
|
|
314
|
+
registered at user scope)
|
|
315
|
+
pantrybase uninstall [--purge] remove the plugin (--purge also deletes the model cache;
|
|
316
|
+
recipes in ./pantrybase are never touched)
|
|
317
|
+
pantrybase doctor check node, native modules, model, plugin registration
|
|
318
|
+
|
|
319
|
+
Recipes (in ./pantrybase of the current directory)
|
|
320
|
+
pantrybase rebuild [--full] [--reembed]
|
|
321
|
+
re-index recipes/*.md (--full re-parses every file,
|
|
322
|
+
--reembed recomputes embeddings)
|
|
323
|
+
pantrybase embed embed pending chunks now
|
|
324
|
+
pantrybase search <query\u2026> quick search from the terminal
|
|
325
|
+
pantrybase ui [--port N] [--open]
|
|
326
|
+
serve the web UI on 127.0.0.1 (default port 7433)
|
|
327
|
+
pantrybase stats counts and paths
|
|
328
|
+
pantrybase version
|
|
329
|
+
`;
|
|
330
|
+
function printSteps(steps) {
|
|
331
|
+
for (const s of steps) console.log(`${s.ok ? "\u2714" : "\u2718"} ${s.step.padEnd(22)} ${s.detail}`);
|
|
332
|
+
return steps.every((s) => s.ok);
|
|
333
|
+
}
|
|
334
|
+
async function main(argv) {
|
|
335
|
+
const [cmd, ...rest] = argv;
|
|
336
|
+
switch (cmd) {
|
|
337
|
+
case "install": {
|
|
338
|
+
console.log(`Installing pantrybase ${pkg.version}\u2026`);
|
|
339
|
+
const r = install({
|
|
340
|
+
model: !rest.includes("--no-model"),
|
|
341
|
+
register: !rest.includes("--no-register")
|
|
342
|
+
});
|
|
343
|
+
printSteps(r.steps);
|
|
344
|
+
console.log(
|
|
345
|
+
r.ok ? "\nDone. Start a new Claude Code session (or run /reload-plugins) and try /pantrybase:ingest or /pantrybase:cook." : "\nSome steps failed \u2014 see above, then run `pantrybase doctor`."
|
|
346
|
+
);
|
|
347
|
+
return r.ok ? 0 : 1;
|
|
348
|
+
}
|
|
349
|
+
case "uninstall": {
|
|
350
|
+
const ok = printSteps(uninstall({ purge: rest.includes("--purge") }));
|
|
351
|
+
return ok ? 0 : 1;
|
|
352
|
+
}
|
|
353
|
+
case "doctor": {
|
|
354
|
+
const root = resolveProjectRoot();
|
|
355
|
+
return printSteps(doctor(root, dataPaths(root).data)) ? 0 : 1;
|
|
356
|
+
}
|
|
357
|
+
case "warm-model": {
|
|
358
|
+
await new Embedder().load();
|
|
359
|
+
return 0;
|
|
360
|
+
}
|
|
361
|
+
case "rebuild": {
|
|
362
|
+
const ctx = openContext(void 0, { reconcile: false });
|
|
363
|
+
const r = reconcile(ctx, {
|
|
364
|
+
full: rest.includes("--full"),
|
|
365
|
+
reembed: rest.includes("--reembed")
|
|
366
|
+
});
|
|
367
|
+
console.log(JSON.stringify(r, null, 2));
|
|
368
|
+
await ctx.embedQueue.run();
|
|
369
|
+
ctx.close();
|
|
370
|
+
return r.errors.length ? 1 : 0;
|
|
371
|
+
}
|
|
372
|
+
case "embed": {
|
|
373
|
+
const ctx = openContext();
|
|
374
|
+
await ctx.embedQueue.run();
|
|
375
|
+
console.log(JSON.stringify(ctx.store.stats(), null, 2));
|
|
376
|
+
ctx.close();
|
|
377
|
+
return 0;
|
|
378
|
+
}
|
|
379
|
+
case "search": {
|
|
380
|
+
const ctx = openContext();
|
|
381
|
+
if (ctx.embedder) await ctx.embedder.load();
|
|
382
|
+
await ctx.embedQueue.run();
|
|
383
|
+
const res = await searchRecipes(ctx, { query: rest.join(" "), limit: 10 });
|
|
384
|
+
for (const r of res.results) {
|
|
385
|
+
console.log(
|
|
386
|
+
`${(r.score ?? 0).toFixed(4)} ${r.slug} \u2014 ${r.title} [${r.matched.join(",")}]`
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
console.log(
|
|
390
|
+
`(${res.results.length} results, vector ${res.vector_used ? "used" : "not used"})`
|
|
391
|
+
);
|
|
392
|
+
ctx.close();
|
|
393
|
+
return 0;
|
|
394
|
+
}
|
|
395
|
+
case "ui": {
|
|
396
|
+
const portArg = rest.indexOf("--port");
|
|
397
|
+
const ctx = openContext();
|
|
398
|
+
const ui = await startUiServer(ctx, {
|
|
399
|
+
port: portArg >= 0 ? Number(rest[portArg + 1]) : void 0,
|
|
400
|
+
version: pkg.version
|
|
401
|
+
});
|
|
402
|
+
console.log(`pantrybase UI: ${ui.url} (data: ${ctx.paths.data}) \u2014 Ctrl-C to stop`);
|
|
403
|
+
if (rest.includes("--open")) {
|
|
404
|
+
const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
405
|
+
spawn(opener, [ui.url], { stdio: "ignore", detached: true }).unref();
|
|
406
|
+
}
|
|
407
|
+
await new Promise(() => {
|
|
408
|
+
});
|
|
409
|
+
return 0;
|
|
410
|
+
}
|
|
411
|
+
case "stats": {
|
|
412
|
+
const ctx = openContext();
|
|
413
|
+
console.log(JSON.stringify({ ...ctx.store.stats(), data_dir: ctx.paths.data }, null, 2));
|
|
414
|
+
ctx.close();
|
|
415
|
+
return 0;
|
|
416
|
+
}
|
|
417
|
+
case "version":
|
|
418
|
+
case "--version":
|
|
419
|
+
case "-v":
|
|
420
|
+
console.log(pkg.version);
|
|
421
|
+
return 0;
|
|
422
|
+
case void 0:
|
|
423
|
+
case "-h":
|
|
424
|
+
case "--help":
|
|
425
|
+
case "help":
|
|
426
|
+
console.log(USAGE);
|
|
427
|
+
return 0;
|
|
428
|
+
default:
|
|
429
|
+
log(`unknown command: ${cmd}`);
|
|
430
|
+
console.log(USAGE);
|
|
431
|
+
return 1;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
main(process.argv.slice(2)).then(
|
|
435
|
+
(code) => process.exit(code),
|
|
436
|
+
(e) => {
|
|
437
|
+
log("fatal:", e instanceof Error ? e.message : e);
|
|
438
|
+
process.exit(1);
|
|
439
|
+
}
|
|
440
|
+
);
|
|
441
|
+
//# sourceMappingURL=cli.js.map
|