@massa-ai/tools-api 1.55.0 → 1.56.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.
Files changed (2) hide show
  1. package/dist/index.js +188 -5
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -601,15 +601,18 @@ var init_massa_ai_config = __esm(() => {
601
601
  security: {
602
602
  corsOrigins: []
603
603
  },
604
- scheduler: DEFAULT_SCHEDULER_CONFIG
604
+ scheduler: DEFAULT_SCHEDULER_CONFIG,
605
+ bootstrap: { rules: {} }
605
606
  };
606
607
  });
607
608
 
608
609
  // ../../packages/shared/dist/config/config-loader.js
609
610
  var exports_config_loader = {};
610
611
  __export(exports_config_loader, {
612
+ writeRawConfig: () => writeRawConfig,
611
613
  writeFileAtomically: () => writeFileAtomically,
612
614
  saveConfig: () => saveConfig,
615
+ readRawConfigStrict: () => readRawConfigStrict,
613
616
  migrateDataDirOnce: () => migrateDataDirOnce,
614
617
  mergeSchedulerSection: () => mergeSchedulerSection,
615
618
  loadRawUserConfig: () => loadRawUserConfig,
@@ -620,12 +623,23 @@ __export(exports_config_loader, {
620
623
  getConfigForEnv: () => getConfigForEnv,
621
624
  getConfigDir: () => getConfigDir,
622
625
  configExists: () => configExists,
623
- __resetMigrationForTests: () => __resetMigrationForTests
626
+ __resetMigrationForTests: () => __resetMigrationForTests,
627
+ ConfigWriteConflictError: () => ConfigWriteConflictError,
628
+ ConfigParseError: () => ConfigParseError
624
629
  });
625
630
  import fs from "fs";
626
631
  import path3 from "path";
627
632
  import os2 from "os";
628
633
  import crypto2 from "crypto";
634
+ function readConfigFileOrEmpty() {
635
+ try {
636
+ return fs.readFileSync(CONFIG_FILE, "utf-8");
637
+ } catch (error) {
638
+ if (error?.code === "ENOENT")
639
+ return "";
640
+ throw error;
641
+ }
642
+ }
629
643
  function getConfigDir() {
630
644
  return CONFIG_DIR;
631
645
  }
@@ -692,6 +706,21 @@ function loadRawUserConfig() {
692
706
  return {};
693
707
  }
694
708
  }
709
+ function readRawConfigStrict() {
710
+ const raw2 = readConfigFileOrEmpty();
711
+ if (raw2 === "")
712
+ return {};
713
+ let parsed;
714
+ try {
715
+ parsed = JSON.parse(raw2);
716
+ } catch (error) {
717
+ throw new ConfigParseError(CONFIG_FILE, error);
718
+ }
719
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
720
+ throw new ConfigParseError(CONFIG_FILE, new Error("parsed value is not a JSON object"));
721
+ }
722
+ return parsed;
723
+ }
695
724
  function loadConfigSafe() {
696
725
  try {
697
726
  return loadConfig();
@@ -746,6 +775,43 @@ function writeFileAtomically(targetPath, content) {
746
775
  function saveConfig(config) {
747
776
  writeFileAtomically(CONFIG_FILE, JSON.stringify(config, null, 2));
748
777
  }
778
+ function writeRawConfig(doc, opts) {
779
+ const onDiskAtStart = readConfigFileOrEmpty();
780
+ if (onDiskAtStart === opts.expectedBytes) {
781
+ writeFileAtomically(CONFIG_FILE, JSON.stringify(doc, null, 2));
782
+ return;
783
+ }
784
+ let original;
785
+ let current;
786
+ try {
787
+ original = opts.expectedBytes === "" ? {} : JSON.parse(opts.expectedBytes);
788
+ } catch (error) {
789
+ throw new ConfigParseError(`${CONFIG_FILE} (caller-supplied expectedBytes)`, error);
790
+ }
791
+ try {
792
+ current = onDiskAtStart === "" ? {} : JSON.parse(onDiskAtStart);
793
+ } catch (error) {
794
+ throw new ConfigParseError(CONFIG_FILE, error);
795
+ }
796
+ const reapplied = { ...current };
797
+ const touchedKeys = new Set([...Object.keys(original), ...Object.keys(doc)]);
798
+ for (const key of touchedKeys) {
799
+ const before = JSON.stringify(original[key]);
800
+ const after = JSON.stringify(doc[key]);
801
+ if (before === after)
802
+ continue;
803
+ if (Object.prototype.hasOwnProperty.call(doc, key)) {
804
+ reapplied[key] = doc[key];
805
+ } else {
806
+ delete reapplied[key];
807
+ }
808
+ }
809
+ const onDiskImmediatelyBeforeWrite = readConfigFileOrEmpty();
810
+ if (onDiskImmediatelyBeforeWrite !== onDiskAtStart) {
811
+ throw new ConfigWriteConflictError(CONFIG_FILE);
812
+ }
813
+ writeFileAtomically(CONFIG_FILE, JSON.stringify(reapplied, null, 2));
814
+ }
749
815
  function initConfig() {
750
816
  if (!fs.existsSync(CONFIG_FILE)) {
751
817
  saveConfig(defaultMassaAiConfig);
@@ -772,12 +838,25 @@ function getConfigForEnv() {
772
838
  env.ENABLE_METRICS = String(config.logging.enableMetrics);
773
839
  return env;
774
840
  }
775
- var CONFIG_DIR, CONFIG_FILE, migrationAttempted = false, tempFileCounter = 0;
841
+ var CONFIG_DIR, CONFIG_FILE, ConfigParseError, ConfigWriteConflictError, migrationAttempted = false, tempFileCounter = 0;
776
842
  var init_config_loader = __esm(() => {
777
843
  init_massa_ai_config();
778
844
  init_xdg();
779
845
  CONFIG_DIR = configDir("massa-ai");
780
846
  CONFIG_FILE = path3.join(CONFIG_DIR, "config.json");
847
+ ConfigParseError = class ConfigParseError extends Error {
848
+ constructor(filePath, cause) {
849
+ const reason = cause instanceof Error ? cause.message : String(cause);
850
+ super(`Failed to parse ${filePath}: ${reason}`);
851
+ this.name = "ConfigParseError";
852
+ }
853
+ };
854
+ ConfigWriteConflictError = class ConfigWriteConflictError extends Error {
855
+ constructor(filePath) {
856
+ super(`${filePath} changed on disk twice while writing \u2014 refusing to overwrite a ` + `concurrent update. Re-read the file and retry.`);
857
+ this.name = "ConfigWriteConflictError";
858
+ }
859
+ };
781
860
  });
782
861
 
783
862
  // ../../packages/shared/dist/env.js
@@ -8572,6 +8651,105 @@ function findRepoRootWithMarker(startDir, marker, maxLevels) {
8572
8651
  }
8573
8652
  var init_repo_root = () => {};
8574
8653
 
8654
+ // ../../packages/shared/dist/bootstrap/rules.js
8655
+ var BOOTSTRAP_RULES, RULES_BY_ID;
8656
+ var init_rules = __esm(() => {
8657
+ BOOTSTRAP_RULES = [
8658
+ {
8659
+ id: "caveman",
8660
+ defaultEnabled: true,
8661
+ description: "Keep communication compressed while preserving technical accuracy."
8662
+ },
8663
+ {
8664
+ id: "massa-ai-router",
8665
+ defaultEnabled: true,
8666
+ description: "Load the massa-ai skill as the workflow router before substantive work."
8667
+ },
8668
+ {
8669
+ id: "persona-router",
8670
+ defaultEnabled: true,
8671
+ description: "Select one cataloged specialist persona after massa-ai context is available."
8672
+ },
8673
+ {
8674
+ id: "dedupe-guardrails",
8675
+ defaultEnabled: true,
8676
+ description: "Reuse already-loaded massa-ai context instead of bulk-loading workflows or references."
8677
+ },
8678
+ {
8679
+ id: "plan-challenge",
8680
+ defaultEnabled: true,
8681
+ description: "Run The Fool as a post-plan challenge gate per the configured policy."
8682
+ },
8683
+ {
8684
+ id: "conversation-feedback",
8685
+ defaultEnabled: true,
8686
+ description: "Emit chat-visible status updates for massa-ai workflow progress."
8687
+ },
8688
+ {
8689
+ id: "indexing-hygiene",
8690
+ defaultEnabled: true,
8691
+ description: "Ignore build output, dependency, and secret paths during indexing and context loading."
8692
+ },
8693
+ {
8694
+ id: "english-code",
8695
+ defaultEnabled: true,
8696
+ description: "Write generated code, identifiers, comments, and commit-facing artifacts in English regardless of conversational language."
8697
+ },
8698
+ {
8699
+ id: "code-comments",
8700
+ defaultEnabled: false,
8701
+ description: "Require API doc blocks and rationale comments on generated code, per code-annotation.md \xA71/\xA72."
8702
+ }
8703
+ ];
8704
+ RULES_BY_ID = new Map(BOOTSTRAP_RULES.map((rule) => [rule.id, rule]));
8705
+ });
8706
+
8707
+ // ../../packages/shared/dist/bootstrap/state.js
8708
+ var BOOTSTRAP_STATE_KEY = "bootstrap", BOOTSTRAP_RULES_KEY = "rules", BOOTSTRAP_STATE_PATH;
8709
+ var init_state2 = __esm(() => {
8710
+ init_config_loader();
8711
+ init_rules();
8712
+ BOOTSTRAP_STATE_PATH = `${BOOTSTRAP_STATE_KEY}.${BOOTSTRAP_RULES_KEY}`;
8713
+ });
8714
+
8715
+ // ../../packages/shared/dist/bootstrap/render.js
8716
+ var init_render = __esm(() => {
8717
+ init_rules();
8718
+ init_state2();
8719
+ });
8720
+
8721
+ // ../../packages/shared/dist/bootstrap/report.js
8722
+ var CLEAN_STATUSES;
8723
+ var init_report = __esm(() => {
8724
+ CLEAN_STATUSES = new Set(["written", "skipped"]);
8725
+ });
8726
+
8727
+ // ../../packages/shared/dist/bootstrap/engine.js
8728
+ var init_engine2 = __esm(() => {
8729
+ init_config_loader();
8730
+ init_hosts();
8731
+ init_state();
8732
+ init_render();
8733
+ init_report();
8734
+ init_state2();
8735
+ });
8736
+
8737
+ // ../../packages/shared/dist/bootstrap/format.js
8738
+ var init_format = __esm(() => {
8739
+ init_rules();
8740
+ });
8741
+
8742
+ // ../../packages/shared/dist/bootstrap/index.js
8743
+ var init_bootstrap = __esm(() => {
8744
+ init_rules();
8745
+ init_state2();
8746
+ init_render();
8747
+ init_report();
8748
+ init_engine2();
8749
+ init_format();
8750
+ init_config_loader();
8751
+ });
8752
+
8575
8753
  // ../../packages/shared/dist/index.js
8576
8754
  var init_dist = __esm(() => {
8577
8755
  init_env();
@@ -8582,6 +8760,7 @@ var init_dist = __esm(() => {
8582
8760
  init_engine();
8583
8761
  init_variant_sync();
8584
8762
  init_repo_root();
8763
+ init_bootstrap();
8585
8764
  init_types();
8586
8765
  init_interfaces();
8587
8766
  init_utils();
@@ -183398,6 +183577,8 @@ function sseFrame(data) {
183398
183577
  `);
183399
183578
  }
183400
183579
  var KNOWN_GENERATOR_FILENAMES = ["generate-skill-artifacts.ts", "generate-subagent-artifacts.ts"];
183580
+ var SH_C_WRAPPER = /^sh -c '(.*)' --$/;
183581
+ var GENERATOR_SEGMENT = /^bun\s+(\S+\.ts)(?:\s+"\$@")?$/;
183401
183582
  function deriveGeneratorScripts(root2) {
183402
183583
  const pkgPath = path42.join(root2, "package.json");
183403
183584
  let raw2;
@@ -183417,12 +183598,14 @@ function deriveGeneratorScripts(root2) {
183417
183598
  if (typeof command !== "string" || command.trim().length === 0) {
183418
183599
  throw new Error(`${pkgPath}'s scripts."generate:artifacts" is missing or not a string`);
183419
183600
  }
183420
- const segments = command.split("&&").map((s) => s.trim()).filter((s) => s.length > 0);
183601
+ const wrapped = SH_C_WRAPPER.exec(command.trim());
183602
+ const chain = wrapped ? wrapped[1] : command;
183603
+ const segments = chain.split("&&").map((s) => s.trim()).filter((s) => s.length > 0);
183421
183604
  if (segments.length === 0) {
183422
183605
  throw new Error(`"generate:artifacts" parsed to zero commands: ${JSON.stringify(command)}`);
183423
183606
  }
183424
183607
  return segments.map((segment) => {
183425
- const match2 = /^bun\s+(\S+\.ts)$/.exec(segment);
183608
+ const match2 = GENERATOR_SEGMENT.exec(segment);
183426
183609
  if (!match2) {
183427
183610
  throw new Error(`"generate:artifacts" segment does not match the expected "bun <script.ts>" shape: ${JSON.stringify(segment)}`);
183428
183611
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@massa-ai/tools-api",
3
- "version": "1.55.0",
3
+ "version": "1.56.0",
4
4
  "author": "luizgmassa",
5
5
  "description": "massa-ai REST API server - Semantic code search, memory, and context compression",
6
6
  "type": "module",
@@ -21,8 +21,8 @@
21
21
  "test": "bun scripts/run-tests-isolated.ts"
22
22
  },
23
23
  "dependencies": {
24
- "@massa-ai/core": "^1.55.0",
25
- "@massa-ai/shared": "^1.55.0",
24
+ "@massa-ai/core": "^1.56.0",
25
+ "@massa-ai/shared": "^1.56.0",
26
26
  "elysia": "^1.2.25",
27
27
  "@elysiajs/swagger": "^1.2.0",
28
28
  "@elysiajs/cors": "^1.2.0",