hafez 2.1.0 → 2.3.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/README.md +72 -5
- package/dist/apply.d.ts +14 -1
- package/dist/apply.js +94 -32
- package/dist/batch-ops.d.ts +31 -27
- package/dist/batch-ops.js +83 -16
- package/dist/cli/block-hook.d.ts +6 -0
- package/dist/cli/block-hook.js +27 -12
- package/dist/cli/commands.d.ts +3 -1
- package/dist/cli/commands.js +183 -73
- package/dist/cli/format.d.ts +11 -3
- package/dist/cli/format.js +61 -4
- package/dist/cli/index.js +40 -19
- package/dist/cli/install.d.ts +9 -0
- package/dist/cli/install.js +36 -15
- package/dist/cli/onboard.js +30 -9
- package/dist/cli/upgrade.js +5 -4
- package/dist/contracts.d.ts +9 -0
- package/dist/contracts.js +9 -0
- package/dist/dates.d.ts +7 -0
- package/dist/dates.js +21 -1
- package/dist/db.d.ts +50 -10
- package/dist/db.js +251 -65
- package/dist/digest.js +14 -7
- package/dist/document.d.ts +2 -0
- package/dist/document.js +2 -2
- package/dist/git.d.ts +13 -2
- package/dist/git.js +121 -14
- package/dist/graph/activity.d.ts +5 -0
- package/dist/graph/activity.js +70 -0
- package/dist/graph/client.js +326 -0
- package/dist/graph/copy-fonts.d.ts +1 -0
- package/dist/graph/copy-fonts.js +13 -0
- package/dist/graph/fields.d.ts +8 -0
- package/dist/graph/fields.js +12 -0
- package/dist/graph/fonts/geist-OFL.txt +93 -0
- package/dist/graph/fonts/geist-mono-OFL.txt +93 -0
- package/dist/graph/fonts/geist-mono.woff2 +0 -0
- package/dist/graph/fonts/geist.woff2 +0 -0
- package/dist/graph/fonts/outfit-OFL.txt +93 -0
- package/dist/graph/fonts/outfit.woff2 +0 -0
- package/dist/graph/fonts.d.ts +14 -0
- package/dist/graph/fonts.js +17 -0
- package/dist/graph/live.d.ts +16 -0
- package/dist/graph/live.js +99 -0
- package/dist/graph/open.d.ts +1 -0
- package/dist/graph/open.js +20 -0
- package/dist/graph/server.d.ts +17 -0
- package/dist/graph/server.js +189 -0
- package/dist/health.d.ts +6 -0
- package/dist/health.js +310 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +66 -18
- package/dist/internal.d.ts +21 -0
- package/dist/internal.js +9 -0
- package/dist/knowledge-index.d.ts +1 -1
- package/dist/read-json.d.ts +26 -0
- package/dist/read-json.js +53 -0
- package/dist/schema.d.ts +2 -0
- package/dist/schema.js +11 -0
- package/dist/stale.d.ts +2 -2
- package/dist/stale.js +4 -9
- package/dist/surfaces/items.d.ts +100 -1
- package/dist/surfaces/items.js +148 -10
- package/dist/surfaces/surfaces.d.ts +8 -5
- package/dist/surfaces/surfaces.js +34 -17
- package/dist/templates.d.ts +2 -0
- package/dist/templates.js +6 -1
- package/dist/types.d.ts +239 -25
- package/dist/validate.js +44 -56
- package/dist/vault.d.ts +29 -9
- package/dist/vault.js +39 -8
- package/dist/workstream.d.ts +17 -0
- package/dist/workstream.js +78 -0
- package/package.json +10 -4
- package/skill/hafez/SKILL.md +16 -7
package/dist/batch-ops.js
CHANGED
|
@@ -101,6 +101,9 @@ export const CreateSessionFieldsSchema = z.object({
|
|
|
101
101
|
insight: nonEmptyText.optional(),
|
|
102
102
|
related: stringList.optional(),
|
|
103
103
|
'session-date': z.string().optional(),
|
|
104
|
+
// Decisions are prose: a list only, never a comma string split apart.
|
|
105
|
+
decisions: z.array(nonEmptyText).optional(),
|
|
106
|
+
entities_touched: stringList.optional(),
|
|
104
107
|
}).strict();
|
|
105
108
|
const CreateEntityBranch = z.object({
|
|
106
109
|
op: z.literal('create'),
|
|
@@ -264,7 +267,9 @@ export function duplicateSessionWarning(slug) {
|
|
|
264
267
|
* batch). The builder runs before the claim — it must see the pre-claim
|
|
265
268
|
* world so a self-referencing parent still fails. */
|
|
266
269
|
function claimNew(ctx, errors, slug, info, build) {
|
|
267
|
-
|
|
270
|
+
// A session note holds its slug too: every kind shares one index row per
|
|
271
|
+
// slug, so a create must not take one a session already has.
|
|
272
|
+
const taken = ctx.existsAnywhere(slug) || ctx.sessionExists(slug);
|
|
268
273
|
if (taken)
|
|
269
274
|
errors.push(`Slug '${slug}' already exists`);
|
|
270
275
|
if (build) {
|
|
@@ -309,6 +314,48 @@ function parentCycleError(slug, parent, ctx) {
|
|
|
309
314
|
const cycle = parentCycle(slug, parent, s => ctx.linksOf(s).parent);
|
|
310
315
|
return cycle ? `Parent '${parent}' would make a cycle: ${cycle.join(' → ')}` : null;
|
|
311
316
|
}
|
|
317
|
+
/** An entity and its own parent or child are never `related` (ADR 0002):
|
|
318
|
+
* `parent` subsumes it. The errors for the links `slug` would carry after
|
|
319
|
+
* the op — the parent named in its related, a related whose parent is
|
|
320
|
+
* `slug`, or a parent whose related names `slug` (a legacy one-way edge) —
|
|
321
|
+
* against the batch so far. */
|
|
322
|
+
function parentSubsumesErrors(slug, links, ctx) {
|
|
323
|
+
const errors = [];
|
|
324
|
+
for (const r of links.related ?? []) {
|
|
325
|
+
if (r === links.parent)
|
|
326
|
+
errors.push(`'${r}' is the parent of '${slug}' — parent subsumes related`);
|
|
327
|
+
else if (ctx.existsAnywhere(r) && ctx.linksOf(r).parent === slug)
|
|
328
|
+
errors.push(`'${r}' is a child of '${slug}' — parent subsumes related`);
|
|
329
|
+
}
|
|
330
|
+
const p = links.parent;
|
|
331
|
+
if (p && ctx.existsAnywhere(p) && ctx.linksOf(p).related?.includes(slug))
|
|
332
|
+
errors.push(`'${p}' names '${slug}' in its related — parent subsumes related`);
|
|
333
|
+
return errors;
|
|
334
|
+
}
|
|
335
|
+
/** Record what the edge writer and dropper will do to the targets: a
|
|
336
|
+
* same-kind `related` edge has two ends, so after `slug`'s related changes
|
|
337
|
+
* from `before` to `after`, every added same-kind target carries `slug` and
|
|
338
|
+
* every dropped one loses it. Cross-kind and unknown targets are left as
|
|
339
|
+
* they are, like the files. */
|
|
340
|
+
function simulateBackEdges(slug, before, after, ctx) {
|
|
341
|
+
const kind = ctx.resolve(slug)?.kind;
|
|
342
|
+
const was = before ?? [];
|
|
343
|
+
const now = after ?? [];
|
|
344
|
+
for (const r of [...now.filter(r => !was.includes(r)), ...was.filter(r => !now.includes(r))]) {
|
|
345
|
+
if (r === slug || !kind || !ctx.existsAnywhere(r) || ctx.resolve(r)?.kind !== kind)
|
|
346
|
+
continue;
|
|
347
|
+
const links = ctx.linksOf(r);
|
|
348
|
+
const rest = (links.related ?? []).filter(x => x !== slug);
|
|
349
|
+
const related = now.includes(r) ? [...rest, slug] : rest;
|
|
350
|
+
ctx.simulateLinks(r, { ...links, related: related.length > 0 ? related : undefined });
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
/** The link fields after an op, simulated for `slug` and mirrored on the
|
|
354
|
+
* targets its related gained or lost. */
|
|
355
|
+
function simulateLinkChange(slug, before, after, ctx) {
|
|
356
|
+
ctx.simulateLinks(slug, after);
|
|
357
|
+
simulateBackEdges(slug, before.related, after.related, ctx);
|
|
358
|
+
}
|
|
312
359
|
// `as const satisfies` rather than a `: OpSpec[]` annotation: it keeps each
|
|
313
360
|
// row's `name` a literal, which is what OpSpecName (and through it the Apply
|
|
314
361
|
// table's key type) is derived from. OP_SPECS below re-exports the rows under
|
|
@@ -381,8 +428,12 @@ const OP_SPEC_ROWS = [
|
|
|
381
428
|
}
|
|
382
429
|
if (target) {
|
|
383
430
|
const links = linkFieldsOf(op.fields);
|
|
384
|
-
if (links)
|
|
385
|
-
|
|
431
|
+
if (links) {
|
|
432
|
+
const before = ctx.linksOf(op.slug);
|
|
433
|
+
const after = { ...before, ...links };
|
|
434
|
+
errors.push(...parentSubsumesErrors(op.slug, after, ctx));
|
|
435
|
+
simulateLinkChange(op.slug, before, after, ctx);
|
|
436
|
+
}
|
|
386
437
|
}
|
|
387
438
|
return { slug: op.slug, errors, primaryCode };
|
|
388
439
|
},
|
|
@@ -398,8 +449,11 @@ const OP_SPEC_ROWS = [
|
|
|
398
449
|
const errors = [];
|
|
399
450
|
const slug = slugify(op.name);
|
|
400
451
|
const primaryCode = claimNew(ctx, errors, slug, { kind: 'entity', type: op.fields.type }, () => ctx.buildEntityFrontmatter(op.name, op.fields));
|
|
401
|
-
if (!primaryCode)
|
|
402
|
-
|
|
452
|
+
if (!primaryCode) {
|
|
453
|
+
const links = { parent: op.fields.parent, related: op.fields.related };
|
|
454
|
+
errors.push(...parentSubsumesErrors(slug, links, ctx));
|
|
455
|
+
simulateLinkChange(slug, {}, links, ctx);
|
|
456
|
+
}
|
|
403
457
|
return { slug, errors, created: errors.length === 0, primaryCode };
|
|
404
458
|
},
|
|
405
459
|
},
|
|
@@ -415,7 +469,7 @@ const OP_SPEC_ROWS = [
|
|
|
415
469
|
const slug = slugify(op.name);
|
|
416
470
|
const primaryCode = claimNew(ctx, errors, slug, { kind: 'knowledge', type: 'knowledge', subtype: op.fields?.subtype }, () => ctx.buildKnowledgeFrontmatter(op.name, (op.fields || {})));
|
|
417
471
|
if (!primaryCode)
|
|
418
|
-
|
|
472
|
+
simulateLinkChange(slug, {}, { related: op.fields?.related }, ctx);
|
|
419
473
|
return { slug, errors, created: errors.length === 0, primaryCode };
|
|
420
474
|
},
|
|
421
475
|
},
|
|
@@ -424,7 +478,7 @@ const OP_SPEC_ROWS = [
|
|
|
424
478
|
op: 'create',
|
|
425
479
|
kind: 'session',
|
|
426
480
|
schema: CreateSessionBranch,
|
|
427
|
-
description: 'Create a new session note linked to an entity. `insight` is an alias for `synthesis` (ignored when `synthesis` is also given).',
|
|
481
|
+
description: 'Create a new session note linked to an entity. `synthesis` writes Summary, `decisions` one bullet each under Decisions, `entities_touched` one `[[slug]]` bullet each under Entities Touched. `insight` is an alias for `synthesis` (ignored when `synthesis` is also given).',
|
|
428
482
|
exampleInclude: ['synthesis'],
|
|
429
483
|
check(op, ctx) {
|
|
430
484
|
const slug = slugify(op.name);
|
|
@@ -452,7 +506,7 @@ const OP_SPEC_ROWS = [
|
|
|
452
506
|
name: 'link',
|
|
453
507
|
op: 'link',
|
|
454
508
|
schema: LinkBranch,
|
|
455
|
-
description: 'Add a parent or related link
|
|
509
|
+
description: 'Add a parent or related link. A same-kind related link (entity↔entity, knowledge↔knowledge) is written on both files; a related naming the entity\'s parent or a child is rejected (parent subsumes related).',
|
|
456
510
|
exampleInclude: [],
|
|
457
511
|
check(op, ctx) {
|
|
458
512
|
const errors = [];
|
|
@@ -470,9 +524,11 @@ const OP_SPEC_ROWS = [
|
|
|
470
524
|
}
|
|
471
525
|
if (!primaryCode) {
|
|
472
526
|
const links = ctx.linksOf(op.slug);
|
|
473
|
-
|
|
527
|
+
const after = op.relation === 'parent'
|
|
474
528
|
? { ...links, parent: op.target }
|
|
475
|
-
: { ...links, related: [...(links.related ?? []).filter(r => r !== op.target), op.target] }
|
|
529
|
+
: { ...links, related: [...(links.related ?? []).filter(r => r !== op.target), op.target] };
|
|
530
|
+
errors.push(...parentSubsumesErrors(op.slug, after, ctx));
|
|
531
|
+
simulateLinkChange(op.slug, links, after, ctx);
|
|
476
532
|
}
|
|
477
533
|
return { slug: op.slug, errors, primaryCode };
|
|
478
534
|
},
|
|
@@ -481,7 +537,7 @@ const OP_SPEC_ROWS = [
|
|
|
481
537
|
name: 'unlink',
|
|
482
538
|
op: 'unlink',
|
|
483
539
|
schema: UnlinkBranch,
|
|
484
|
-
description: 'Remove a parent or related link
|
|
540
|
+
description: 'Remove a parent or related link. A same-kind related link is dropped from both files, a legacy one-way edge from whichever file carries it.',
|
|
485
541
|
exampleInclude: [],
|
|
486
542
|
check(op, ctx) {
|
|
487
543
|
const errors = [];
|
|
@@ -492,9 +548,13 @@ const OP_SPEC_ROWS = [
|
|
|
492
548
|
}
|
|
493
549
|
else {
|
|
494
550
|
const links = ctx.linksOf(op.slug);
|
|
495
|
-
|
|
551
|
+
simulateLinkChange(op.slug, links, op.relation === 'parent'
|
|
496
552
|
? { ...links, parent: links.parent === op.target ? undefined : links.parent }
|
|
497
|
-
: { ...links, related: links.related?.filter(r => r !== op.target) });
|
|
553
|
+
: { ...links, related: links.related?.filter(r => r !== op.target) }, ctx);
|
|
554
|
+
// A legacy one-way edge may live on the target alone: the dropper
|
|
555
|
+
// takes it there too.
|
|
556
|
+
if (op.relation === 'related' && !links.related?.includes(op.target))
|
|
557
|
+
simulateBackEdges(op.slug, [op.target], [], ctx);
|
|
498
558
|
}
|
|
499
559
|
return { slug: op.slug, errors, primaryCode };
|
|
500
560
|
},
|
|
@@ -538,7 +598,7 @@ const OP_SPEC_ROWS = [
|
|
|
538
598
|
name: 'delete',
|
|
539
599
|
op: 'delete',
|
|
540
600
|
schema: DeleteBranch,
|
|
541
|
-
description: 'Delete a knowledge or session note. An entity is never deleted — retire it with `hafez update <slug> --status done`. Rejected while
|
|
601
|
+
description: 'Delete a knowledge or session note. An entity is never deleted — retire it with `hafez update <slug> --status done`. The back-edges the note owns (a knowledge note in its own related that names it back) are dropped with it, in the same commit. Rejected while any other entity or knowledge note links to the note (parent/related): unlink or re-point those first — an earlier op in the same batch counts.',
|
|
542
602
|
exampleInclude: [],
|
|
543
603
|
addressesSessions: true,
|
|
544
604
|
check(op, ctx) {
|
|
@@ -558,12 +618,19 @@ const OP_SPEC_ROWS = [
|
|
|
558
618
|
}
|
|
559
619
|
else {
|
|
560
620
|
// Only knowledge can be linked to: a parent/related slug must name an
|
|
561
|
-
// entity or knowledge note, never a session.
|
|
562
|
-
|
|
621
|
+
// entity or knowledge note, never a session. A same-kind back-edge
|
|
622
|
+
// the note owns — a note in its own related that names it back — is
|
|
623
|
+
// the other end of its edge, dropped with it (#243), not a blocker.
|
|
624
|
+
const own = target ? ctx.linksOf(op.slug).related ?? [] : [];
|
|
625
|
+
const referrers = target
|
|
626
|
+
? ctx.referrers(op.slug).filter(r => !(own.includes(r) && ctx.resolve(r)?.kind === target.kind))
|
|
627
|
+
: [];
|
|
563
628
|
if (referrers.length > 0) {
|
|
564
629
|
errors.push(`'${op.slug}' is still linked from ${referrers.join(', ')} (parent/related) — unlink or re-point those first; an earlier op in the same batch counts`);
|
|
565
630
|
}
|
|
566
631
|
else {
|
|
632
|
+
if (target)
|
|
633
|
+
simulateBackEdges(op.slug, own, [], ctx);
|
|
567
634
|
ctx.simulateDelete(op.slug, target ? 'knowledge' : 'session');
|
|
568
635
|
}
|
|
569
636
|
}
|
package/dist/cli/block-hook.d.ts
CHANGED
|
@@ -7,3 +7,9 @@ export interface BlockHookCtx extends ConfigHome {
|
|
|
7
7
|
}
|
|
8
8
|
/** The render, or null for any failure: the caller prints nothing. */
|
|
9
9
|
export declare function blockHook(ctx: BlockHookCtx): Promise<string | null>;
|
|
10
|
+
/** The working directory, its git root, and in a linked worktree the main
|
|
11
|
+
* repository's root. */
|
|
12
|
+
export declare function foldersOf(cwd: string): string[];
|
|
13
|
+
/** Every remote's URL, normalised. */
|
|
14
|
+
export declare function remoteUrls(cwd: string): string[];
|
|
15
|
+
export declare function resourceMatches(resource: string, folders: string[], remotes: string[]): boolean;
|
package/dist/cli/block-hook.js
CHANGED
|
@@ -26,11 +26,16 @@ export async function blockHook(ctx) {
|
|
|
26
26
|
// leave an index file in it.
|
|
27
27
|
if (typeof vaultPath !== 'string' || !isVault(vaultPath))
|
|
28
28
|
return null;
|
|
29
|
-
const
|
|
29
|
+
const dir = ctx.cwd ?? process.cwd();
|
|
30
|
+
// A deleted working directory: no folder to match.
|
|
31
|
+
if (!existsSync(dir))
|
|
32
|
+
return null;
|
|
33
|
+
const cwd = canonical(dir);
|
|
30
34
|
const folders = foldersOf(cwd);
|
|
31
35
|
const remotes = remoteUrls(cwd);
|
|
32
36
|
const { createHafez } = await import('../index.js');
|
|
33
|
-
const
|
|
37
|
+
const os = createHafez({ vaultPath, git: { push: false } });
|
|
38
|
+
const { items } = await os.query({ filter: 'all' }).finally(() => os.close());
|
|
34
39
|
const matches = items
|
|
35
40
|
.filter(e => folders.some(f => basename(f) === e.slug) || (e.resource !== null && resourceMatches(e.resource, folders, remotes)))
|
|
36
41
|
// Active first: the status tuple is ordered active, paused, done.
|
|
@@ -53,21 +58,33 @@ function git(cwd, ...args) {
|
|
|
53
58
|
}
|
|
54
59
|
/** The working directory, its git root, and in a linked worktree the main
|
|
55
60
|
* repository's root. */
|
|
56
|
-
function foldersOf(cwd) {
|
|
61
|
+
export function foldersOf(cwd) {
|
|
57
62
|
const folders = [cwd];
|
|
58
63
|
const out = git(cwd, 'rev-parse', '--path-format=absolute', '--show-toplevel', '--git-common-dir');
|
|
59
64
|
const [top, common] = out?.split('\n') ?? [];
|
|
60
65
|
// Before git 2.31 `--path-format` is echoed back, not obeyed: no git root.
|
|
61
66
|
if (top && common && isAbsolute(top) && isAbsolute(common)) {
|
|
62
|
-
|
|
67
|
+
const root = canonical(top);
|
|
68
|
+
folders.push(root);
|
|
63
69
|
// A linked worktree shares the main checkout's `.git` as its common dir.
|
|
64
|
-
|
|
65
|
-
|
|
70
|
+
// The shape is read off git's own path: a symlinked `.git` resolves to a
|
|
71
|
+
// directory with some other name.
|
|
72
|
+
const main = canonical(dirname(common));
|
|
73
|
+
if (basename(common) === '.git' && main !== root)
|
|
74
|
+
folders.push(main);
|
|
66
75
|
}
|
|
67
76
|
return [...new Set(folders)];
|
|
68
77
|
}
|
|
78
|
+
/** One spelling per folder, so paths from git, the working directory and a
|
|
79
|
+
* `resource` compare equal: git prints `C:/…` on Windows, realpath `C:\…`.
|
|
80
|
+
* The native realpath, since only it returns the filesystem's own letter case
|
|
81
|
+
* (`c:\users\…` is `C:\Users\…`) and long names for 8.3 ones. */
|
|
82
|
+
function canonical(path) {
|
|
83
|
+
const abs = resolve(path);
|
|
84
|
+
return existsSync(abs) ? realpathSync.native(abs) : abs;
|
|
85
|
+
}
|
|
69
86
|
/** Every remote's URL, normalised. */
|
|
70
|
-
function remoteUrls(cwd) {
|
|
87
|
+
export function remoteUrls(cwd) {
|
|
71
88
|
const out = git(cwd, 'config', '--get-regexp', '^remote\\..*\\.url$');
|
|
72
89
|
return out ? out.split('\n').map(line => normaliseUrl(line.slice(line.indexOf(' ') + 1))) : [];
|
|
73
90
|
}
|
|
@@ -81,10 +98,8 @@ function normaliseUrl(url) {
|
|
|
81
98
|
.replace(/\/+$/, '')
|
|
82
99
|
.replace(/\.git$/, '');
|
|
83
100
|
}
|
|
84
|
-
function resourceMatches(resource, folders, remotes) {
|
|
85
|
-
if (isAbsolute(resource))
|
|
86
|
-
|
|
87
|
-
return folders.includes(existsSync(path) ? realpathSync(path) : path);
|
|
88
|
-
}
|
|
101
|
+
export function resourceMatches(resource, folders, remotes) {
|
|
102
|
+
if (isAbsolute(resource))
|
|
103
|
+
return folders.includes(canonical(resource));
|
|
89
104
|
return remotes.includes(normaliseUrl(resource));
|
|
90
105
|
}
|
package/dist/cli/commands.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export interface CommandOpts {
|
|
|
9
9
|
export declare function cmdRead(os: Hafez, args: string[], opts?: CommandOpts): Promise<string>;
|
|
10
10
|
/** Every flag the query parser accepts, for the branch-support matrix. */
|
|
11
11
|
export declare const QUERY_FLAG_NAMES: string[];
|
|
12
|
-
export type QueryBranch = 'entity' | 'knowledge' | 'all' | 'related-to';
|
|
12
|
+
export type QueryBranch = 'entity' | 'knowledge' | 'session' | 'all' | 'related-to';
|
|
13
13
|
/** Which flags each kind branch actually applies. A branch that cannot honour
|
|
14
14
|
* a flag rejects it (below) instead of dropping it: `--kind knowledge --filter
|
|
15
15
|
* stale` used to return every knowledge note with exit 0, and `--confidence`
|
|
@@ -36,6 +36,8 @@ export declare function cmdCapture(os: Hafez, args: string[], opts?: CommandOpts
|
|
|
36
36
|
export declare function cmdPromote(os: Hafez, args: string[], opts?: CommandOpts): Promise<string>;
|
|
37
37
|
export declare function cmdDelete(os: Hafez, args: string[], opts?: CommandOpts): Promise<string>;
|
|
38
38
|
export declare function cmdValidate(os: Hafez, args: string[], opts?: CommandOpts): Promise<string>;
|
|
39
|
+
export declare function cmdHealth(os: Hafez, args: string[], opts?: CommandOpts): Promise<string>;
|
|
40
|
+
export declare function cmdGraph(os: Hafez, args: string[], opts?: CommandOpts): Promise<string>;
|
|
39
41
|
export declare function cmdIndexRebuild(os: Hafez): Promise<string>;
|
|
40
42
|
export declare function cmdSync(os: Hafez, args: string[]): Promise<string>;
|
|
41
43
|
export declare function cmdStats(os: Hafez, args: string[], opts?: CommandOpts): Promise<string>;
|