daftari 1.6.0 → 1.7.1

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 CHANGED
@@ -7,6 +7,58 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.7.1] - 2026-05-19
11
+
12
+ ### Fixed
13
+
14
+ - **MCP server hang at startup** (#35, PR #36). The server no longer re-embeds
15
+ the entire vault on every launch and no longer waits for indexing to finish
16
+ before opening the stdio transport. Three compounding bugs are fixed:
17
+ (1) `main()` always called `reindexVault` even when `.daftari/index.db`
18
+ already reflected the files on disk — every restart re-embedded the whole
19
+ vault (~25 minutes on a 3,500-file vault); now a path→mtime manifest is
20
+ persisted in the SQLite meta table and compared on startup, so an
21
+ unchanged vault skips the embedding pass entirely. (2) The
22
+ `StdioServerTransport` opened only after indexing completed, so MCP
23
+ clients could not answer `initialize` for the whole duration; the
24
+ transport now opens first and indexing — when required — runs as a
25
+ background task. (3) Progress was emitted only on TTY stderr, leaving
26
+ every real (non-TTY) MCP client with zero output during a cold start;
27
+ progress now streams on stderr in both TTY (\\r-updated) and pipe (full
28
+ line every ~5%) modes. A new in-process `IndexState`
29
+ (`ready`/`indexing`/`error` + progress) gates `vault_search`,
30
+ `vault_search_related`, `vault_reindex`, `vault_write`, `vault_append`,
31
+ `vault_promote`, and `vault_deprecate` while indexing — those tools
32
+ return a progress-bearing busy error so clients can retry. Read tools
33
+ (`vault_read`, `vault_index`, `vault_status`) are unaffected because
34
+ they go to the filesystem, not the index. `--reindex` remains the one
35
+ synchronous mode (rebuild, exit).
36
+
37
+ ## [1.7.0] - 2026-05-19
38
+
39
+ ### Added
40
+
41
+ - **Pre-write transform hooks** (#32). New `pre_write_transform` hook phase
42
+ runs before `validateFrontmatter` and can derive or override frontmatter
43
+ fields. Returns `Partial<Frontmatter>`. Refuses via throw. Existing
44
+ `pre_write` validators continue to run unchanged after validation. Closes
45
+ the gap where v1.6.0 hooks could observe and reject but could not derive
46
+ built-in fields. Declared under `hooks.pre_write_transform` in
47
+ `.daftari/config.yaml`; the runner merges each hook's patch Object.assign
48
+ style — shallow, last-writer-wins. Phase order is rigid:
49
+ `pre_write_transform` (declaration order), then `validateFrontmatter`, then
50
+ `pre_write` (declaration order), regardless of config layout. Fires for
51
+ `vault_write` and `vault_append`; `vault_promote` and `vault_deprecate`
52
+ bypass it, matching the `pre_write` bypass.
53
+
54
+ ### Changed
55
+
56
+ - The existing `pre_write` hook surface continues to half-mutate: a mutation
57
+ to `rawFrontmatter` inside a `pre_write` hook propagates for extension
58
+ fields but not for built-in fields. This behavior is preserved for
59
+ backward compatibility but is now implementation detail — new mutations
60
+ should use `pre_write_transform`.
61
+
10
62
  ## [1.6.0] - 2026-05-19
11
63
 
12
64
  ### Added
package/README.md CHANGED
@@ -320,6 +320,59 @@ validate-only. Returning a non-array, or an array containing malformed issue
320
320
  objects, is itself reported as a blocking issue tagged with the hook path —
321
321
  hook bugs surface as loud failures, not silent passes.
322
322
 
323
+ ### Transform hooks
324
+
325
+ A `pre_write` hook can observe and reject, but it cannot *change* the
326
+ frontmatter a write lands. **Transform hooks** can. A transform hook runs in an
327
+ earlier phase — before built-in schema validation — so it can derive or
328
+ override frontmatter fields the validator would otherwise reject as missing.
329
+
330
+ Transform hooks are declared under their own key, `pre_write_transform`:
331
+
332
+ ```yaml
333
+ hooks:
334
+ pre_write_transform:
335
+ - path: .daftari/hooks/derive-status.mjs
336
+ pre_write:
337
+ - path: .daftari/hooks/forbid-status-skip.mjs
338
+ ```
339
+
340
+ The phase order is fixed regardless of how the config lists the blocks: every
341
+ `pre_write_transform` hook runs (in declared order), then built-in schema
342
+ validation, then every `pre_write` validator (in declared order). A transform
343
+ always runs before any validator sees the frontmatter.
344
+
345
+ A transform hook returns a `Partial<Frontmatter>` patch — *not* a list of
346
+ issues:
347
+
348
+ ```ts
349
+ // .daftari/hooks/derive-status.mjs
350
+ //
351
+ // context = { path: string; operation: 'create' | 'update' | 'append' }
352
+ export default function deriveStatus(frontmatter, context) {
353
+ if (frontmatter.decision_status === "ACTIVE") {
354
+ return { status: "canonical" };
355
+ }
356
+ return {}; // no change
357
+ }
358
+ ```
359
+
360
+ The runner merges each patch into the candidate frontmatter **`Object.assign`
361
+ style**: shallow, last-writer-wins. A key present in the patch replaces the
362
+ existing value outright — arrays are replaced whole, never appended to or
363
+ merged element-wise. When two transforms target the same field, the
364
+ later-declared one wins. Each transform sees the merged output of every
365
+ transform declared before it.
366
+
367
+ A transform **refuses by throwing** — it does not return issues. A throw
368
+ becomes a synthetic blocking issue tagged with the hook path, identical to the
369
+ `pre_write` throw mechanism. Returning anything that is not an object (an
370
+ array, a primitive, `null`) is likewise a blocking issue.
371
+
372
+ Because transforms run before validation, a transform that sets an invalid
373
+ value — a `status` outside the allowed set, say — is caught by the built-in
374
+ validator exactly as a bad user-supplied value would be.
375
+
323
376
  ### Trust model
324
377
 
325
378
  Hooks are **trusted code**. They run in the same Node process as the daftari
@@ -333,15 +386,18 @@ register hooks in v1.
333
386
 
334
387
  ### Scope and limits in v1
335
388
 
336
- - **Surfaces:** only `pre_write`. Future surfaces (`pre_read`, `post_write`,
389
+ - **Surfaces:** `pre_write` (validators) and `pre_write_transform`
390
+ (field-deriving transforms). Future surfaces (`pre_read`, `post_write`,
337
391
  etc.) are reserved — unrecognised keys under `hooks:` are a loud config
338
392
  error, not a silent skip.
339
- - **Operations:** hooks fire for `vault_write` (create + update) and
340
- `vault_append`. `vault_promote` and `vault_deprecate` deliberately bypass
341
- hooks — they're narrow metadata mutations the server controls end-to-end.
342
- - **Validate-only:** the hook return value is a list of issues. Mutation
343
- (a hook that patches frontmatter on the way through) is a deliberate
344
- follow-up see issue #29 for the dialogue.
393
+ - **Operations:** both hook surfaces fire for `vault_write` (create + update)
394
+ and `vault_append`. `vault_promote` and `vault_deprecate` deliberately
395
+ bypass hooks — they're narrow metadata mutations the server controls
396
+ end-to-end.
397
+ - **Two phases:** a `pre_write` hook returns a list of issues and can only
398
+ reject. A `pre_write_transform` hook returns a `Partial<Frontmatter>` patch
399
+ and can derive or override fields before validation — see "Transform
400
+ hooks" above.
345
401
  - **Sync:** hook bodies are synchronous functions. The loader is async
346
402
  (it has to dynamic-import the module), but each individual hook call is
347
403
  not awaited.
@@ -1,5 +1,7 @@
1
1
  import { type Result } from "../frontmatter/types.js";
2
- import type { HookDeclaration, LoadedHook } from "./types.js";
2
+ import type { HookDeclaration, LoadedHook, LoadedTransformHook } from "./types.js";
3
3
  export declare function loadHook(vaultRoot: string, decl: HookDeclaration): Promise<Result<LoadedHook, Error>>;
4
+ export declare function loadPreWriteTransformHook(vaultRoot: string, decl: HookDeclaration): Promise<Result<LoadedTransformHook, Error>>;
4
5
  export declare function loadHooks(vaultRoot: string, declarations: HookDeclaration[]): Promise<Result<LoadedHook[], Error>>;
6
+ export declare function loadPreWriteTransformHooks(vaultRoot: string, declarations: HookDeclaration[]): Promise<Result<LoadedTransformHook[], Error>>;
5
7
  //# sourceMappingURL=loader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/hooks/loader.ts"],"names":[],"mappings":"AAUA,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAgB,MAAM,YAAY,CAAC;AAyB5E,wBAAsB,QAAQ,CAC5B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAwBpC;AAKD,wBAAsB,SAAS,CAC7B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,eAAe,EAAE,GAC9B,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,KAAK,CAAC,CAAC,CAQtC"}
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/hooks/loader.ts"],"names":[],"mappings":"AAUA,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EACV,eAAe,EACf,UAAU,EACV,mBAAmB,EAGpB,MAAM,YAAY,CAAC;AA0DpB,wBAAsB,QAAQ,CAC5B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAIpC;AAKD,wBAAsB,yBAAyB,CAC7C,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC,MAAM,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC,CAI7C;AAKD,wBAAsB,SAAS,CAC7B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,eAAe,EAAE,GAC9B,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,KAAK,CAAC,CAAC,CAQtC;AAID,wBAAsB,0BAA0B,CAC9C,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,eAAe,EAAE,GAC9B,OAAO,CAAC,MAAM,CAAC,mBAAmB,EAAE,EAAE,KAAK,CAAC,CAAC,CAQ/C"}
@@ -26,11 +26,13 @@ function resolveHookPath(vaultRoot, hookPath) {
26
26
  }
27
27
  return ok(abs);
28
28
  }
29
- // Loads one hook module. The module's default export must be a function;
30
- // anything else returns Result.err. The function is not validated beyond
31
- // being callable TypeScript types are erased at runtime and v1 does not
32
- // ship a typed helper (see the optional defineHook polish in #29).
33
- export async function loadHook(vaultRoot, decl) {
29
+ // Imports a hook module and returns its default export, which must be a
30
+ // function — anything else returns Result.err. Shared by both the pre_write
31
+ // and pre_write_transform loaders: the import, path-escape, and
32
+ // default-is-function checks are identical; only the typed cast the caller
33
+ // applies differs. The function is not validated beyond being callable —
34
+ // TypeScript types are erased at runtime.
35
+ async function importHookDefault(vaultRoot, decl) {
34
36
  const resolved = resolveHookPath(vaultRoot, decl.path);
35
37
  if (!resolved.ok)
36
38
  return resolved;
@@ -50,7 +52,24 @@ export async function loadHook(vaultRoot, decl) {
50
52
  if (typeof mod.default !== "function") {
51
53
  return err(new Error(`hook '${decl.path}' must export a default function, got ${typeof mod.default}`));
52
54
  }
53
- return ok({ declaration: decl, hook: mod.default });
55
+ return ok(mod.default);
56
+ }
57
+ // Loads one pre_write hook module. The module's default export must be a
58
+ // function; anything else returns Result.err.
59
+ export async function loadHook(vaultRoot, decl) {
60
+ const fn = await importHookDefault(vaultRoot, decl);
61
+ if (!fn.ok)
62
+ return fn;
63
+ return ok({ declaration: decl, hook: fn.value });
64
+ }
65
+ // Loads one pre_write_transform hook module. Mirrors loadHook — same import,
66
+ // path-escape, and default-is-function checks — but the loaded function is
67
+ // typed as a transform hook (returns Partial<Frontmatter>, not issues).
68
+ export async function loadPreWriteTransformHook(vaultRoot, decl) {
69
+ const fn = await importHookDefault(vaultRoot, decl);
70
+ if (!fn.ok)
71
+ return fn;
72
+ return ok({ declaration: decl, hook: fn.value });
54
73
  }
55
74
  // Loads every declared hook in order. Returns Result.err on the first load
56
75
  // failure — a vault with a broken hook declaration refuses to write, same
@@ -65,4 +84,16 @@ export async function loadHooks(vaultRoot, declarations) {
65
84
  }
66
85
  return ok(loaded);
67
86
  }
87
+ // Loads every declared pre_write_transform hook in order. Fails fast on the
88
+ // first bad declaration, identical to loadHooks.
89
+ export async function loadPreWriteTransformHooks(vaultRoot, declarations) {
90
+ const loaded = [];
91
+ for (const decl of declarations) {
92
+ const result = await loadPreWriteTransformHook(vaultRoot, decl);
93
+ if (!result.ok)
94
+ return result;
95
+ loaded.push(result.value);
96
+ }
97
+ return ok(loaded);
98
+ }
68
99
  //# sourceMappingURL=loader.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/hooks/loader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/hooks/loader.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,9 @@
1
1
  import type { ValidationIssue } from "../frontmatter/types.js";
2
- import type { HookContext, LoadedHook } from "./types.js";
2
+ import type { HookContext, LoadedHook, LoadedTransformHook } from "./types.js";
3
3
  export declare function runPreWriteHooks(hooks: LoadedHook[], frontmatter: Record<string, unknown>, context: HookContext): ValidationIssue[];
4
+ export interface TransformRunResult {
5
+ merged: Record<string, unknown>;
6
+ issues: ValidationIssue[];
7
+ }
8
+ export declare function runPreWriteTransformHooks(hooks: LoadedTransformHook[], frontmatter: Record<string, unknown>, context: HookContext): TransformRunResult;
4
9
  //# sourceMappingURL=runner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/hooks/runner.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE1D,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,UAAU,EAAE,EACnB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,OAAO,EAAE,WAAW,GACnB,eAAe,EAAE,CAoCnB"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/hooks/runner.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE/E,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,UAAU,EAAE,EACnB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,OAAO,EAAE,WAAW,GACnB,eAAe,EAAE,CAoCnB;AAaD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B;AAcD,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,mBAAmB,EAAE,EAC5B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,OAAO,EAAE,WAAW,GACnB,kBAAkB,CA2BpB"}
@@ -39,4 +39,52 @@ export function runPreWriteHooks(hooks, frontmatter, context) {
39
39
  }
40
40
  return issues;
41
41
  }
42
+ // Describes a transform hook's return value for an error message: "null",
43
+ // "array", or its typeof.
44
+ function describeReturn(v) {
45
+ if (v === null)
46
+ return "null";
47
+ if (Array.isArray(v))
48
+ return "array";
49
+ return typeof v;
50
+ }
51
+ // Executes pre_write_transform hooks against a candidate frontmatter. Hooks
52
+ // run in declaration order; each receives a fresh shallow copy of the
53
+ // *current* merged state, so a later transform sees an earlier one's output
54
+ // but cannot mutate the running state in place. A hook's Partial<Frontmatter>
55
+ // return is merged Object.assign-style — shallow, last-writer-wins, arrays
56
+ // replaced whole.
57
+ //
58
+ // A hook that throws becomes a synthetic blocking issue whose field is the
59
+ // hook path and whose message names the underlying error; nothing from a
60
+ // thrown hook is merged. A non-object return (array, primitive, null) is
61
+ // likewise a synthetic blocking issue with no merge. Every hook still runs
62
+ // even after an earlier hook failed — matching the run-all pre_write contract.
63
+ export function runPreWriteTransformHooks(hooks, frontmatter, context) {
64
+ const issues = [];
65
+ let merged = { ...frontmatter };
66
+ for (const { declaration, hook } of hooks) {
67
+ let partial;
68
+ try {
69
+ partial = hook({ ...merged }, context);
70
+ }
71
+ catch (e) {
72
+ const reason = e instanceof Error ? e.message : String(e);
73
+ issues.push({
74
+ field: declaration.path,
75
+ message: `transform hook threw: ${reason}`,
76
+ });
77
+ continue;
78
+ }
79
+ if (partial === null || typeof partial !== "object" || Array.isArray(partial)) {
80
+ issues.push({
81
+ field: declaration.path,
82
+ message: `transform hook returned non-object (got ${describeReturn(partial)})`,
83
+ });
84
+ continue;
85
+ }
86
+ merged = { ...merged, ...partial };
87
+ }
88
+ return { merged, issues };
89
+ }
42
90
  //# sourceMappingURL=runner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/hooks/runner.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,wEAAwE;AACxE,0EAA0E;AAC1E,0EAA0E;AAC1E,mEAAmE;AAKnE,MAAM,UAAU,gBAAgB,CAC9B,KAAmB,EACnB,WAAoC,EACpC,OAAoB;IAEpB,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,KAAK,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,KAAK,EAAE,CAAC;QAC1C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YAC1C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC3B,MAAM,CAAC,IAAI,CAAC;oBACV,KAAK,EAAE,WAAW,CAAC,IAAI;oBACvB,OAAO,EAAE,gCAAgC,OAAO,MAAM,GAAG;iBAC1D,CAAC,CAAC;gBACH,SAAS;YACX,CAAC;YACD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,IACE,KAAK,KAAK,IAAI;oBACd,OAAO,KAAK,KAAK,QAAQ;oBACzB,OAAQ,KAAyB,CAAC,KAAK,KAAK,QAAQ;oBACpD,OAAQ,KAAyB,CAAC,OAAO,KAAK,QAAQ,EACtD,CAAC;oBACD,MAAM,CAAC,IAAI,CAAC;wBACV,KAAK,EAAE,WAAW,CAAC,IAAI;wBACvB,OAAO,EAAE,kCAAkC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE;qBACnE,CAAC,CAAC;oBACH,SAAS;gBACX,CAAC;gBACD,MAAM,CAAC,IAAI,CAAC,KAAwB,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,MAAM,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC1D,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK,EAAE,WAAW,CAAC,IAAI;gBACvB,OAAO,EAAE,eAAe,MAAM,EAAE;aACjC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/hooks/runner.ts"],"names":[],"mappings":"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"}
@@ -1,18 +1,24 @@
1
- import type { ValidationIssue } from "../frontmatter/types.js";
1
+ import type { Frontmatter, ValidationIssue } from "../frontmatter/types.js";
2
2
  export type HookOperation = "create" | "update" | "append";
3
3
  export interface HookContext {
4
4
  path: string;
5
5
  operation: HookOperation;
6
6
  }
7
7
  export type PreWriteHook = (frontmatter: Record<string, unknown>, context: HookContext) => ValidationIssue[];
8
+ export type PreWriteTransformHook = (frontmatter: Record<string, unknown>, context: HookContext) => Partial<Frontmatter>;
8
9
  export interface HookDeclaration {
9
10
  path: string;
10
11
  }
11
12
  export interface HookConfig {
12
13
  preWrite: HookDeclaration[];
14
+ preWriteTransform: HookDeclaration[];
13
15
  }
14
16
  export interface LoadedHook {
15
17
  declaration: HookDeclaration;
16
18
  hook: PreWriteHook;
17
19
  }
20
+ export interface LoadedTransformHook {
21
+ declaration: HookDeclaration;
22
+ hook: PreWriteTransformHook;
23
+ }
18
24
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/hooks/types.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAO/D,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAM3D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,aAAa,CAAC;CAC1B;AAOD,MAAM,MAAM,YAAY,GAAG,CACzB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,OAAO,EAAE,WAAW,KACjB,eAAe,EAAE,CAAC;AAKvB,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;CACd;AAKD,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAKD,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,eAAe,CAAC;IAC7B,IAAI,EAAE,YAAY,CAAC;CACpB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/hooks/types.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAO5E,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAM3D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,aAAa,CAAC;CAC1B;AAOD,MAAM,MAAM,YAAY,GAAG,CACzB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,OAAO,EAAE,WAAW,KACjB,eAAe,EAAE,CAAC;AASvB,MAAM,MAAM,qBAAqB,GAAG,CAClC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,OAAO,EAAE,WAAW,KACjB,OAAO,CAAC,WAAW,CAAC,CAAC;AAM1B,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;CACd;AAMD,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,iBAAiB,EAAE,eAAe,EAAE,CAAC;CACtC;AAKD,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,eAAe,CAAC;IAC7B,IAAI,EAAE,YAAY,CAAC;CACpB;AAID,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,eAAe,CAAC;IAC7B,IAAI,EAAE,qBAAqB,CAAC;CAC7B"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAmBA,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASrE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAE3D;AAED,wBAAsB,IAAI,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CAyEhF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgCA,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASrE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAE3D;AAED,wBAAsB,IAAI,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CAuFhF"}
package/dist/index.js CHANGED
@@ -1,16 +1,24 @@
1
1
  // Daftari MCP server entry point.
2
2
  //
3
3
  // Parses `--vault <path>`, verifies the vault directory exists, loads the RBAC
4
- // config, builds the search index, then serves the tools over stdio under the
5
- // access identity given by `--user` / `--role`. Diagnostics go to stderr so
6
- // they never corrupt the stdio JSON-RPC stream on stdout.
4
+ // config, opens the MCP stdio transport, then if the index isn't already
5
+ // current runs a reindex in the background. Diagnostics go to stderr so they
6
+ // never corrupt the stdio JSON-RPC stream on stdout.
7
7
  //
8
- // `--reindex` rebuilds the search index and exits without starting the server.
8
+ // The transport opens before indexing on purpose: a cold reindex on a large
9
+ // vault is minutes long, and a client must be able to answer `initialize` and
10
+ // list tools immediately. Tools that depend on the index consult
11
+ // `getIndexStatus()` and reply "still indexing — N/M chunks" until the
12
+ // background pass finishes.
13
+ //
14
+ // `--reindex` is the one synchronous mode: rebuild the index, exit, do not
15
+ // start the server.
9
16
  import { resolve } from "node:path";
10
17
  import { pathToFileURL } from "node:url";
11
18
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
12
19
  import { GUEST_ROLE, resolveAccess } from "./access/rbac.js";
13
- import { reindexVault } from "./search/reindex.js";
20
+ import { markIndexError, markIndexing, markIndexReady, setIndexProgress, } from "./search/index-state.js";
21
+ import { isIndexFresh, reindexVault } from "./search/reindex.js";
14
22
  import { createServer } from "./server.js";
15
23
  import { directoryExists } from "./storage/local.js";
16
24
  import { loadConfig } from "./utils/config.js";
@@ -58,41 +66,98 @@ export async function main(argv = process.argv.slice(2)) {
58
66
  if (access.role === null && roleName !== GUEST_ROLE) {
59
67
  process.stderr.write(`daftari: warning: role '${roleName}' not found in config — running as deny-all guest\n`);
60
68
  }
61
- // Build (or rebuild) the search index. With --reindex this is the whole job.
62
- // On an interactive terminal, report embedding progress on a single line so
63
- // a large-vault reindex is not silent; in non-TTY contexts (CI, pipes) the
64
- // final summary line below is the only output.
65
- let progressShown = false;
66
- const reindexed = await reindexVault(vaultRoot, {
67
- onProgress: process.stderr.isTTY
68
- ? (done, total) => {
69
- progressShown = true;
70
- process.stderr.write(`\rdaftari: embedding ${done}/${total} chunks`);
71
- }
72
- : undefined,
73
- });
74
- if (progressShown)
75
- process.stderr.write("\n");
76
- if (reindexed.ok) {
77
- const r = reindexed.value;
78
- process.stderr.write(`daftari: indexed ${r.documentCount} docs, ${r.chunkCount} chunks ` +
79
- `(vectors ${r.vectorEnabled ? "on" : "off"})\n`);
80
- }
81
- else {
82
- // A failed index is not fatal: lexical search still works and the search
83
- // tools retry indexing lazily on first use.
84
- process.stderr.write(`daftari: warning: index build failed: ${reindexed.error.message}\n`);
85
- }
86
- if (argv.includes("--reindex")) {
87
- if (!reindexed.ok)
69
+ // The persisted index is a derived cache: if every file on disk matches the
70
+ // manifest written by the last reindex, the on-disk index already reflects
71
+ // the vault and we can skip the embedding pass entirely (~25 min on a
72
+ // multi-thousand-file vault). --reindex forces a rebuild even when fresh.
73
+ const forceReindex = argv.includes("--reindex");
74
+ // --reindex is the one synchronous mode: rebuild and exit. No transport,
75
+ // no background work. The IndexState is updated for completeness but no
76
+ // tool runs against it in this mode.
77
+ if (forceReindex) {
78
+ markIndexing();
79
+ const reindexed = await reindexVault(vaultRoot, makeProgressReporter());
80
+ if (reindexed.ok) {
81
+ const r = reindexed.value;
82
+ markIndexReady();
83
+ process.stderr.write(`daftari: indexed ${r.documentCount} docs, ${r.chunkCount} chunks ` +
84
+ `(vectors ${r.vectorEnabled ? "on" : "off"})\n`);
85
+ }
86
+ else {
87
+ markIndexError(reindexed.error.message);
88
+ process.stderr.write(`daftari: warning: index build failed: ${reindexed.error.message}\n`);
88
89
  process.exitCode = 1;
90
+ }
89
91
  return;
90
92
  }
93
+ // Open MCP transport first so the client can answer `initialize` and
94
+ // `tools/list` immediately. Indexing — if needed — runs as a background
95
+ // task; tools that depend on the index will respond "still indexing" until
96
+ // it completes.
91
97
  const server = createServer(vaultRoot, access);
92
98
  const transport = new StdioServerTransport();
93
99
  await server.connect(transport);
94
100
  process.stderr.write(`daftari: serving vault at ${vaultRoot} (stdio) — ` +
95
101
  `user=${access.user} role=${access.roleName}\n`);
102
+ const fresh = await isIndexFresh(vaultRoot);
103
+ if (fresh) {
104
+ process.stderr.write(`daftari: index is up to date — skipping reindex\n`);
105
+ markIndexReady();
106
+ return;
107
+ }
108
+ // Background reindex. The promise is intentionally not awaited — main()
109
+ // returns once the transport is up, and the indexing pass runs to
110
+ // completion alongside the live server.
111
+ markIndexing();
112
+ process.stderr.write(`daftari: starting background reindex…\n`);
113
+ void runBackgroundReindex(vaultRoot);
114
+ }
115
+ async function runBackgroundReindex(vaultRoot) {
116
+ try {
117
+ const reindexed = await reindexVault(vaultRoot, makeProgressReporter());
118
+ if (reindexed.ok) {
119
+ const r = reindexed.value;
120
+ markIndexReady();
121
+ process.stderr.write(`daftari: indexed ${r.documentCount} docs, ${r.chunkCount} chunks ` +
122
+ `(vectors ${r.vectorEnabled ? "on" : "off"})\n`);
123
+ }
124
+ else {
125
+ markIndexError(reindexed.error.message);
126
+ process.stderr.write(`daftari: warning: background index build failed: ${reindexed.error.message}\n`);
127
+ }
128
+ }
129
+ catch (e) {
130
+ const reason = e instanceof Error ? (e.stack ?? e.message) : String(e);
131
+ markIndexError(reason);
132
+ process.stderr.write(`daftari: warning: background indexer crashed: ${reason}\n`);
133
+ }
134
+ }
135
+ // Builds a ReindexOptions whose onProgress streams to both stderr (for
136
+ // operator visibility) and the in-process IndexState (so tools can return
137
+ // progress to MCP clients). TTY stderr gets a \r-updated single line; piped
138
+ // stderr gets a full line every ~5% so MCP-client logs stay readable instead
139
+ // of going silent for tens of minutes.
140
+ function makeProgressReporter() {
141
+ const PIPE_STEP = 0.05;
142
+ let nextPipeMark = 0;
143
+ return {
144
+ onProgress: (done, total) => {
145
+ setIndexProgress(done, total);
146
+ if (total === 0)
147
+ return;
148
+ if (process.stderr.isTTY) {
149
+ process.stderr.write(`\rdaftari: embedding ${done}/${total} chunks`);
150
+ if (done === total)
151
+ process.stderr.write("\n");
152
+ return;
153
+ }
154
+ const ratio = done / total;
155
+ if (ratio >= nextPipeMark || done === total) {
156
+ process.stderr.write(`daftari: embedding ${done}/${total} chunks\n`);
157
+ nextPipeMark = Math.floor(ratio / PIPE_STEP + 1) * PIPE_STEP;
158
+ }
159
+ },
160
+ };
96
161
  }
97
162
  // Auto-run only when this module is the process entry point (e.g. `tsx
98
163
  // src/index.ts`). When imported (by cli.ts or tests) it stays inert.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export type IndexStatus = "ready" | "indexing" | "error";
2
+ export interface IndexSnapshot {
3
+ status: IndexStatus;
4
+ done: number;
5
+ total: number;
6
+ error: string | null;
7
+ startedAt: string | null;
8
+ finishedAt: string | null;
9
+ }
10
+ export declare function getIndexStatus(): IndexSnapshot;
11
+ export declare function markIndexing(): void;
12
+ export declare function setIndexProgress(done: number, total: number): void;
13
+ export declare function markIndexReady(): void;
14
+ export declare function markIndexError(message: string): void;
15
+ export declare function resetIndexState(): void;
16
+ export declare function indexingBusyMessage(snapshot: IndexSnapshot): string;
17
+ //# sourceMappingURL=index-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-state.d.ts","sourceRoot":"","sources":["../../src/search/index-state.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,OAAO,CAAC;AAEzD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAeD,wBAAgB,cAAc,IAAI,aAAa,CAE9C;AAED,wBAAgB,YAAY,IAAI,IAAI,CASnC;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAGlE;AAED,wBAAgB,cAAc,IAAI,IAAI,CAOrC;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAOpD;AAID,wBAAgB,eAAe,IAAI,IAAI,CAEtC;AAKD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,CAKnE"}