seekstone 0.19.0 → 0.20.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/README.md CHANGED
@@ -163,6 +163,7 @@ Every write tool (`append_note`, `patch_note`, `patch_frontmatter`, `replace_in_
163
163
  | `SEEKSTONE_MODEL_PATH` | no | Directory holding the Model2Vec embedding model (default: where `fetch-model` puts the selected model). |
164
164
  | `SEEKSTONE_CACHE_DIR` | no | Cache root for the model and per-vault embedding caches (default `~/.cache/seekstone`). |
165
165
  | `SEEKSTONE_BUNDLED_MODEL_DIR` | no | Set by the `seekstone-semantic.mcpb` bundle's manifest — sharded model files shipped inside the extension, reassembled into the model directory at boot (disk-only, hash-verified). Not usually set by hand. |
166
+ | `SEEKSTONE_INSTRUCTIONS` | no | Path to a file whose contents become the MCP server's `instructions` string (surfaced to clients alongside the tool list). A relative path resolves against the vault root. Read once at boot, trimmed, capped at 16 KB (truncated with a warning past that). Missing, unreadable, or empty after trim means no instructions — never a boot failure. |
166
167
 
167
168
  ---
168
169
 
package/dist/index.js CHANGED
@@ -192,7 +192,7 @@ var init_fetch_model = __esm({
192
192
 
193
193
  // src/index.ts
194
194
  import { homedir } from "os";
195
- import { resolve as resolve2 } from "path";
195
+ import { resolve as resolve3 } from "path";
196
196
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
197
197
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
198
198
  import {
@@ -439,6 +439,8 @@ Optional environment:
439
439
  SEEKSTONE_SEMANTIC_MODEL potion-base-8M (default) | potion-retrieval-32M (bigger, more accurate)
440
440
  SEEKSTONE_MODEL_PATH Override the embedding-model directory
441
441
  SEEKSTONE_CACHE_DIR Override the cache root (default ~/.cache/seekstone)
442
+ SEEKSTONE_INSTRUCTIONS Path to a file whose contents become the MCP
443
+ "instructions" (relative paths resolve against the vault)
442
444
 
443
445
  Add to Claude Code:
444
446
  claude mcp add seekstone --env SEEKSTONE_VAULT=/path/to/vault -- npx -y seekstone
@@ -3790,6 +3792,47 @@ async function runInit(opts, deps) {
3790
3792
  return { ok: true, exitCode: 0, output: out, wrotePath: configPath, backupPath };
3791
3793
  }
3792
3794
 
3795
+ // src/instructions.ts
3796
+ import { readFileSync } from "fs";
3797
+ import { isAbsolute, resolve as resolve2 } from "path";
3798
+ var MAX_BYTES = 16 * 1024;
3799
+ function truncateUtf8(text, maxBytes) {
3800
+ let bytes = 0;
3801
+ let out = "";
3802
+ for (const ch of text) {
3803
+ const chBytes = Buffer.byteLength(ch, "utf8");
3804
+ if (bytes + chBytes > maxBytes) break;
3805
+ out += ch;
3806
+ bytes += chBytes;
3807
+ }
3808
+ return out;
3809
+ }
3810
+ function resolveInstructions(env, vaultRoot2, log2) {
3811
+ const raw = (env.SEEKSTONE_INSTRUCTIONS ?? "").trim();
3812
+ if (raw === "") return void 0;
3813
+ const path2 = isAbsolute(raw) ? raw : resolve2(vaultRoot2, raw);
3814
+ let content;
3815
+ try {
3816
+ content = readFileSync(path2, "utf8");
3817
+ } catch (err) {
3818
+ log2.warn("cannot read SEEKSTONE_INSTRUCTIONS file; starting without instructions", {
3819
+ path: path2,
3820
+ error: err instanceof Error ? err.message : String(err)
3821
+ });
3822
+ return void 0;
3823
+ }
3824
+ let trimmed = content.trim();
3825
+ if (trimmed === "") return void 0;
3826
+ const bytes = Buffer.byteLength(trimmed, "utf8");
3827
+ if (bytes > MAX_BYTES) {
3828
+ log2.warn("SEEKSTONE_INSTRUCTIONS file exceeds 16 KB; truncated", { path: path2, bytes });
3829
+ trimmed = truncateUtf8(trimmed, MAX_BYTES).trim();
3830
+ if (trimmed === "") return void 0;
3831
+ }
3832
+ log2.info("instructions attached", { bytes: Buffer.byteLength(trimmed, "utf8") });
3833
+ return trimmed;
3834
+ }
3835
+
3793
3836
  // src/process-guards.ts
3794
3837
  function installProcessGuards(log2) {
3795
3838
  const onUnhandledRejection = (reason) => {
@@ -4894,6 +4937,7 @@ var ALL_TOOLS = [
4894
4937
  description: "eq/ne compare scalars; contains matches array membership or substring; exists/missing test key presence; gt/gte/lt/lte compare numbers or strings (ISO dates sort correctly)."
4895
4938
  },
4896
4939
  value: {
4940
+ type: ["string", "number", "boolean"],
4897
4941
  description: "Comparison value. Required for every op except exists/missing."
4898
4942
  }
4899
4943
  },
@@ -5200,8 +5244,26 @@ var ALL_TOOLS = [
5200
5244
  properties: {
5201
5245
  path: { type: "string", description: "Vault-relative path to the note." },
5202
5246
  target: {
5203
- type: "object",
5204
- description: 'Exactly one of: { heading: "Section Title" } or { block: "block-id" } (without the ^ prefix).'
5247
+ description: 'Exactly one of: { heading: "Section Title" } or { block: "block-id" } (without the ^ prefix).',
5248
+ anyOf: [
5249
+ {
5250
+ type: "object",
5251
+ properties: {
5252
+ heading: { type: "string", description: "Heading text (without # markers)." }
5253
+ },
5254
+ required: ["heading"]
5255
+ },
5256
+ {
5257
+ type: "object",
5258
+ properties: {
5259
+ block: {
5260
+ type: "string",
5261
+ description: "Block reference ID (without the ^ prefix)."
5262
+ }
5263
+ },
5264
+ required: ["block"]
5265
+ }
5266
+ ]
5205
5267
  },
5206
5268
  operation: {
5207
5269
  type: "string",
@@ -5468,9 +5530,9 @@ function startWatcher(ctx2, log2, opts) {
5468
5530
  opts?.onRawEvent?.("unlink", abs, relPath);
5469
5531
  if (relPath.endsWith(".md")) remove(relPath);
5470
5532
  });
5471
- const ready = new Promise((resolve3) => {
5533
+ const ready = new Promise((resolve4) => {
5472
5534
  watcher2.once("ready", () => {
5473
- resolve3();
5535
+ resolve4();
5474
5536
  });
5475
5537
  });
5476
5538
  return {
@@ -5480,7 +5542,7 @@ function startWatcher(ctx2, log2, opts) {
5480
5542
  }
5481
5543
 
5482
5544
  // src/index.ts
5483
- var VERSION = true ? "0.19.0" : "0.0.0-dev";
5545
+ var VERSION = true ? "0.20.1" : "0.0.0-dev";
5484
5546
  var intent = parseCliIntent(process.argv.slice(2));
5485
5547
  if (intent === "version") {
5486
5548
  process.stdout.write(`${VERSION}
@@ -5527,7 +5589,7 @@ if (!rawVaultRoot) {
5527
5589
  log.error("SEEKSTONE_VAULT env var is required");
5528
5590
  process.exit(1);
5529
5591
  }
5530
- var vaultRoot = resolve2(rawVaultRoot);
5592
+ var vaultRoot = resolve3(rawVaultRoot);
5531
5593
  var policy = parseWritePolicy(process.env);
5532
5594
  if (policy.readOnly) log.info("read-only mode", { env: "SEEKSTONE_READ_ONLY" });
5533
5595
  if (policy.writeGlobs) log.info("write paths scoped", { globs: policy.writeGlobs });
@@ -5579,7 +5641,11 @@ if (semanticCfg) {
5579
5641
  }
5580
5642
  var watcher = startWatcher(ctx, log);
5581
5643
  process.on("exit", () => void watcher.stop());
5582
- var server = new Server({ name: "seekstone", version: VERSION }, { capabilities: { tools: {} } });
5644
+ var instructions = resolveInstructions(process.env, vaultRoot, log);
5645
+ var server = new Server(
5646
+ { name: "seekstone", version: VERSION },
5647
+ { capabilities: { tools: {} }, instructions }
5648
+ );
5583
5649
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
5584
5650
  tools: visibleTools(ctx.policy)
5585
5651
  }));