@appchy/jarvis 0.1.44 → 0.1.45

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/bin.js CHANGED
@@ -5770,9 +5770,9 @@ var VENDOR_SUBPATHS = [
5770
5770
  "backends",
5771
5771
  "embedders",
5772
5772
  "finders",
5773
+ "labelers",
5773
5774
  "linkers",
5774
5775
  "persistences",
5775
- "rerankers",
5776
5776
  "stores"
5777
5777
  ];
5778
5778
  function toVendorAlias(dir) {
@@ -5809,11 +5809,11 @@ function validateConfig(value, path22) {
5809
5809
  const search3 = c.search;
5810
5810
  if (search3 !== void 0) {
5811
5811
  if (typeof search3.embedder?.embed !== "function")
5812
- fail("`search.embedder` must be an embedder (e.g. localEmbeddings())");
5812
+ fail("`search.embedder` must be an embedder (e.g. openaiEmbeddings())");
5813
5813
  if (search3.store !== void 0 && typeof search3.store.query !== "function")
5814
5814
  fail("`search.store` must be a vector store");
5815
5815
  if (search3.reranker !== void 0 && typeof search3.reranker.rerank !== "function")
5816
- fail("`search.reranker` must be a reranker (e.g. localReranker())");
5816
+ fail("`search.reranker` must be a reranker");
5817
5817
  }
5818
5818
  }
5819
5819
 
@@ -5822,6 +5822,7 @@ async function buildEmbeddings(config2, graph2) {
5822
5822
  const cfg = config2.search;
5823
5823
  if (!cfg) return void 0;
5824
5824
  const embedder2 = cfg.embedder.resolve ? await cfg.embedder.resolve() : cfg.embedder;
5825
+ if (!embedder2) return declined(cfg.embedder, "no semantic index was built");
5825
5826
  const storeImpl = cfg.store;
5826
5827
  const nodes = cfg.types ? cfg.types.flatMap((t) => graph2.nodes(t)) : graph2.nodes();
5827
5828
  const ctx = { repoRoot: config2.repoRoot };
@@ -5880,6 +5881,7 @@ async function loadEmbeddings(config2, graph2) {
5880
5881
  const cfg = config2.search;
5881
5882
  if (!cfg) return void 0;
5882
5883
  const embedder2 = cfg.embedder.resolve ? await cfg.embedder.resolve() : cfg.embedder;
5884
+ if (!embedder2) return declined(cfg.embedder, "search is lexical");
5883
5885
  await probeEmbedder(embedder2);
5884
5886
  const storeImpl = cfg.store;
5885
5887
  const nodes = cfg.types ? cfg.types.flatMap((t) => graph2.nodes(t)) : graph2.nodes();
@@ -5911,6 +5913,13 @@ function toRuntime(cfg, embedder2, storeImpl, items) {
5911
5913
  ...cfg.confidence ? { confidence: cfg.confidence } : {}
5912
5914
  };
5913
5915
  }
5916
+ function declined(embedder2, consequence) {
5917
+ process.stderr.write(
5918
+ `[data:warn] embedder ${embedder2.name} is not available on this machine \u2014 ${consequence}. Token-overlap (BM25) search still applies.
5919
+ `
5920
+ );
5921
+ return void 0;
5922
+ }
5914
5923
  async function probeEmbedder(embedder2) {
5915
5924
  try {
5916
5925
  await embedder2.embed(["probe"]);
@@ -9613,7 +9622,7 @@ import { createRequire as createRequire2 } from "module";
9613
9622
  var _require = createRequire2(import.meta.url);
9614
9623
  var VERSION2 = _require("../package.json").version ?? "0.0.0";
9615
9624
  var IS_DEV = String(_require("../package.json").name ?? "").endsWith("-dev");
9616
- var SHA = "d64996d";
9625
+ var SHA = "86c8e54";
9617
9626
  var BUILT = "2026-09-07";
9618
9627
  var BUILD = SHA ?? "source";
9619
9628
  var BUILD_LABEL = `${SHA ? `${VERSION2} (${SHA}${BUILT ? ` ${BUILT}` : ""})` : `${VERSION2} (source)`}${IS_DEV ? " \u2014 development build" : ""}`;
@@ -10614,6 +10623,33 @@ function register15(program) {
10614
10623
  });
10615
10624
  }
10616
10625
 
10626
+ // src/commands/model.ts
10627
+ function register16(program) {
10628
+ const model = program.command("model").description("Model access for the map's semantic search, on this machine");
10629
+ model.command("key").argument("[key]", "The OpenAI key to store. Omit it to see what is set.").option("--show", "Say whether a key is set, without printing it").option("--clear", "Forget the stored key").description("Set the OpenAI key the map embeds with").action((key, opts) => {
10630
+ const config2 = loadConfig();
10631
+ if (!config2) {
10632
+ console.error("This machine has no jarvis config yet \u2014 run `jarvis init` first.");
10633
+ process.exitCode = 1;
10634
+ return;
10635
+ }
10636
+ if (opts.clear) {
10637
+ saveConfig({ ...config2, openaiApiKey: void 0 });
10638
+ console.log("Forgotten. The map will build with no semantic index.");
10639
+ return;
10640
+ }
10641
+ if (!key || opts.show) {
10642
+ console.log(
10643
+ config2.openaiApiKey ? `A key is set (\u2026${config2.openaiApiKey.slice(-4)}). The map embeds with it.` : "No key set. The map builds with no semantic index and search stays lexical."
10644
+ );
10645
+ if (!key) console.log("Set one with `jarvis model key <key>`.");
10646
+ return;
10647
+ }
10648
+ saveConfig({ ...config2, openaiApiKey: key });
10649
+ console.log("Stored. Run `jarvis build graph` to build the semantic index.");
10650
+ });
10651
+ }
10652
+
10617
10653
  // src/graph/build.ts
10618
10654
  import { mkdirSync as mkdirSync2, readFileSync as readFileSync6, rmSync, statSync as statSync3, writeFileSync as writeFileSync3 } from "fs";
10619
10655
  import { dirname as dirname5, resolve as resolve7 } from "path";
@@ -10787,12 +10823,6 @@ async function runBuild(cwd, argv = []) {
10787
10823
  if (argv.includes("--rebuild")) process.env.JARVIS_DATA_REBUILD = "1";
10788
10824
  else process.env.JARVIS_DATA_REFRESH = "1";
10789
10825
  if (argv.includes("--label")) process.env.JARVIS_DATA_LABEL = "1";
10790
- const labelBackend = readFlag(argv, "--backend");
10791
- if (labelBackend) process.env.JARVIS_DATA_BACKEND = labelBackend;
10792
- const labelModel = readFlag(argv, "--model");
10793
- if (labelModel) process.env.JARVIS_DATA_MODEL = labelModel;
10794
- const labelTier = readFlag(argv, "--tier");
10795
- if (labelTier) process.env.JARVIS_DATA_TIER = labelTier;
10796
10826
  const lock = acquireBuildLock(cwd);
10797
10827
  if (!lock) {
10798
10828
  process.stderr.write(
@@ -10846,13 +10876,6 @@ ${formatLedger(ledger)}
10846
10876
  }
10847
10877
  return errors > 0 ? 1 : 0;
10848
10878
  }
10849
- function readFlag(argv, flag2) {
10850
- const exact = argv.indexOf(flag2);
10851
- if (exact >= 0) return argv[exact + 1];
10852
- const prefix = `${flag2}=`;
10853
- const inline = argv.find((arg) => arg.startsWith(prefix));
10854
- return inline ? inline.slice(prefix.length) : void 0;
10855
- }
10856
10879
  var DEFAULT_STALE_MS = 10 * 60 * 1e3;
10857
10880
  function acquireBuildLock(repoRoot, options = {}) {
10858
10881
  const staleMs = options.staleMs ?? DEFAULT_STALE_MS;
@@ -10913,16 +10936,13 @@ function loadEnvFile(path22) {
10913
10936
  }
10914
10937
 
10915
10938
  // src/commands/build.ts
10916
- function register16(program) {
10939
+ function register17(program) {
10917
10940
  const build2 = program.command("build").description("Build an artifact from this repo");
10918
- build2.command("graph").description("Read the repo's jarvis.config.ts, build the graph, and say what is wrong with it").option("--repo <path>", "The repo to map. Default: the working directory").option("--rebuild", "LAST RESORT: throw the graph away and re-extract from scratch").option("--label", "Re-name the detected communities through the configured labeler").option("--gate", "Fail when a governance class has more findings than this repo carries").option("--backend <name>", "Label the communities as this backend").option("--model <name>", "Label the communities with this model").option("--tier <tier>", "Label the communities at this tier").action(async (opts) => {
10941
+ build2.command("graph").description("Read the repo's jarvis.config.ts, build the graph, and say what is wrong with it").option("--repo <path>", "The repo to map. Default: the working directory").option("--rebuild", "LAST RESORT: throw the graph away and re-extract from scratch").option("--label", "Re-name the detected communities through the configured labeler").option("--gate", "Fail when a governance class has more findings than this repo carries").action(async (opts) => {
10919
10942
  const argv = [
10920
10943
  ...opts.rebuild ? ["--rebuild"] : [],
10921
10944
  ...opts.label ? ["--label"] : [],
10922
- ...opts.gate ? ["--gate"] : [],
10923
- ...opts.backend ? ["--backend", opts.backend] : [],
10924
- ...opts.model ? ["--model", opts.model] : [],
10925
- ...opts.tier ? ["--tier", opts.tier] : []
10945
+ ...opts.gate ? ["--gate"] : []
10926
10946
  ];
10927
10947
  process.exitCode = await runBuild(resolveRepo(opts.repo), argv);
10928
10948
  });
@@ -10976,7 +10996,7 @@ function isRedirected(req) {
10976
10996
  }
10977
10997
 
10978
10998
  // src/commands/dev.ts
10979
- function register17(program) {
10999
+ function register18(program) {
10980
11000
  const dev = program.command("dev").description("Run a development build in a repo, without replacing the installed jarvis");
10981
11001
  dev.command("use").argument("[where]", "'here' for the working directory, 'all' for every repo", "here").option("--root <path>", "The checkout to run. Default: the one already recorded").description("Point a repo at the development build").action((where, opts) => {
10982
11002
  const current = readDevRedirect();
@@ -11690,7 +11710,7 @@ async function brief2(repo) {
11690
11710
  }
11691
11711
 
11692
11712
  // src/commands/serve.ts
11693
- function register18(program) {
11713
+ function register19(program) {
11694
11714
  program.command("serve").description("Serve this repo to an agent over stdio \u2014 what an .mcp.json launches").option("--repo <path>", "The repo to serve. Default: the working directory").action(async (opts) => {
11695
11715
  const repo = resolveRepo(opts.repo);
11696
11716
  const problem = harnessProblem();
@@ -11752,7 +11772,7 @@ function refuseNamedConfigDir() {
11752
11772
  );
11753
11773
  return true;
11754
11774
  }
11755
- function register19(program) {
11775
+ function register20(program) {
11756
11776
  const hooks = program.command("hooks").description("Wire this machine's Claude Code to jarvis \u2014 no pairing, no daemon");
11757
11777
  hooks.command("install").description("Install the Claude Code hooks (the session block and the rules on edit)").action(() => {
11758
11778
  if (refuseNamedConfigDir()) process.exit(1);
@@ -11807,7 +11827,7 @@ Open Claude Code in a repo that has a work/ tree to see them.`);
11807
11827
 
11808
11828
  // src/commands/work.ts
11809
11829
  import { spawnSync as spawnSync3 } from "child_process";
11810
- function register20(program) {
11830
+ function register21(program) {
11811
11831
  program.command("work").description("The board \u2014 take work, prove it, finish it").argument("[args...]", "Passed to the harness untouched").allowUnknownOption().passThroughOptions().helpOption(false).action((passed) => {
11812
11832
  const problem = harnessProblem();
11813
11833
  if (problem) {
@@ -11850,6 +11870,7 @@ function createCli() {
11850
11870
  register18(program);
11851
11871
  register19(program);
11852
11872
  register20(program);
11873
+ register21(program);
11853
11874
  return program;
11854
11875
  }
11855
11876