@arkhera30/cli 0.3.5 → 0.3.7

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 +46 -19
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -601,6 +601,12 @@ var ANVIL_SERVICE = ` # \u2500\u2500 Anvil \u2500\u2500\u2500\u2500\u2500\u2500
601
601
  - ANVIL_SYNC_INTERVAL=\${ANVIL_SYNC_INTERVAL:-300}
602
602
  - ANVIL_DEBOUNCE_SECONDS=\${ANVIL_DEBOUNCE_SECONDS:-5}
603
603
  - GITHUB_TOKEN=\${GITHUB_TOKEN:-}
604
+ - TYPESENSE_HOST=typesense
605
+ - TYPESENSE_PORT=8108
606
+ - TYPESENSE_API_KEY=\${TYPESENSE_API_KEY:-horus-local-key}
607
+ depends_on:
608
+ typesense:
609
+ condition: service_healthy
604
610
  networks:
605
611
  - horus-net
606
612
  restart: unless-stopped
@@ -624,8 +630,11 @@ var FORGE_SERVICE = ` # \u2500\u2500 Forge \u2500\u2500\u2500\u2500\u2500\u2500
624
630
  ports:
625
631
  - "\${FORGE_PORT:-8200}:8200"
626
632
  volumes:
633
+ - \${HORUS_DATA_PATH}/config:/data/config:rw
627
634
  - \${HORUS_DATA_PATH}/registry:/data/registry:rw
628
635
  - \${HORUS_DATA_PATH}/workspaces:/data/workspaces:rw
636
+ - \${HORUS_DATA_PATH}/repos:/data/horus-repos:rw
637
+ - \${HORUS_DATA_PATH}/sessions:/data/sessions:rw
629
638
  - \${HOST_REPOS_PATH}:/data/repos:ro
630
639
  environment:
631
640
  - HORUS_RUNTIME=\${HORUS_RUNTIME:-docker}
@@ -633,6 +642,8 @@ var FORGE_SERVICE = ` # \u2500\u2500 Forge \u2500\u2500\u2500\u2500\u2500\u2500
633
642
  - FORGE_HOST=0.0.0.0
634
643
  - FORGE_REGISTRY_PATH=/data/registry
635
644
  - FORGE_WORKSPACES_PATH=/data/workspaces
645
+ - FORGE_CONFIG_PATH=/data/config
646
+ - FORGE_MANAGED_REPOS_PATH=/data/horus-repos
636
647
  - FORGE_REGISTRY_REPO_URL=\${FORGE_REGISTRY_REPO_URL:-}
637
648
  - FORGE_SYNC_INTERVAL=\${FORGE_SYNC_INTERVAL:-300}
638
649
  - FORGE_ANVIL_URL=http://anvil:8100
@@ -644,9 +655,14 @@ var FORGE_SERVICE = ` # \u2500\u2500 Forge \u2500\u2500\u2500\u2500\u2500\u2500
644
655
  - FORGE_HOST_FORGE_URL=http://localhost:\${FORGE_PORT:-8200}
645
656
  - FORGE_SCAN_PATHS=\${FORGE_SCAN_PATHS:-/data/repos}
646
657
  - GITHUB_TOKEN=\${GITHUB_TOKEN:-}
658
+ - TYPESENSE_HOST=typesense
659
+ - TYPESENSE_PORT=8108
660
+ - TYPESENSE_API_KEY=\${TYPESENSE_API_KEY:-horus-local-key}
647
661
  depends_on:
648
662
  anvil:
649
663
  condition: service_healthy
664
+ typesense:
665
+ condition: service_healthy
650
666
  vault-router:
651
667
  condition: service_healthy
652
668
  networks:
@@ -726,7 +742,11 @@ var HORUS_UI_SERVICE = ` # \u2500\u2500 Horus UI \u2500\u2500\u2500\u2500\u2500
726
742
  timeout: 5s
727
743
  start_period: 30s
728
744
  retries: 3`;
729
- var TEST_COMPOSE_CONTENT = `# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
745
+ function generateTestComposeFile(config) {
746
+ const vaultEntries = Object.entries(config.vaults).sort(([a], [b]) => a.localeCompare(b));
747
+ const defaultVaultEntry = vaultEntries.find(([, v]) => v.default);
748
+ const vaultName = defaultVaultEntry ? defaultVaultEntry[0] : vaultEntries[0]?.[0] ?? "default";
749
+ return `# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
730
750
  # Horus \u2014 Shadow Stack Overlay for Integration Testing
731
751
  # \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
732
752
  # Usage (managed by \`horus test-env acquire\`):
@@ -739,9 +759,6 @@ var TEST_COMPOSE_CONTENT = `# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u
739
759
  #
740
760
  # All TEST_PORT_* and TEST_DATA_PATH are set by \`horus test-env acquire\`.
741
761
  # Slot 0 defaults: ports 9100-9399, data at ~/Horus/data/test-env/slot-0/
742
- #
743
- # NOTE: vault-personal is assumed as the primary vault name. If your config
744
- # uses a different vault name, set TEST_VAULT_NAME accordingly.
745
762
  # \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
746
763
 
747
764
  services:
@@ -751,11 +768,11 @@ services:
751
768
  volumes:
752
769
  - "\${TEST_DATA_PATH:-/tmp/horus-test}/notes:/data/notes:rw"
753
770
 
754
- vault-personal:
771
+ vault-${vaultName}:
755
772
  ports:
756
773
  - "\${TEST_PORT_VAULT_SVC:-9101}:8000"
757
774
  volumes:
758
- - "\${TEST_DATA_PATH:-/tmp/horus-test}/vaults/personal:/data/knowledge-repo:rw"
775
+ - "\${TEST_DATA_PATH:-/tmp/horus-test}/vaults/${vaultName}:/data/knowledge-repo:rw"
759
776
 
760
777
  vault-router:
761
778
  ports:
@@ -769,8 +786,10 @@ services:
769
786
  ports:
770
787
  - "\${TEST_PORT_FORGE:-9250}:8200"
771
788
  volumes:
789
+ - "\${TEST_DATA_PATH:-/tmp/horus-test}/config:/data/config:rw"
772
790
  - "\${TEST_DATA_PATH:-/tmp/horus-test}/registry:/data/registry:rw"
773
791
  - "\${TEST_DATA_PATH:-/tmp/horus-test}/workspaces:/data/workspaces:rw"
792
+ - "\${TEST_DATA_PATH:-/tmp/horus-test}/repos:/data/horus-repos:rw"
774
793
  - "\${TEST_DATA_PATH:-/tmp/horus-test}/sessions:/data/sessions:rw"
775
794
 
776
795
  typesense:
@@ -783,6 +802,7 @@ services:
783
802
  ports:
784
803
  - "\${TEST_PORT_UI:-9260}:8400"
785
804
  `;
805
+ }
786
806
  function generateComposeFile(config, runtime) {
787
807
  const vaultEntries = Object.entries(config.vaults).sort(([a], [b]) => a.localeCompare(b));
788
808
  const vaultServices = vaultEntries.map(([name, vault], index) => {
@@ -932,7 +952,7 @@ function installComposeFile(config, runtime) {
932
952
  ensureHorusDir();
933
953
  const content = generateComposeFile(config, runtime);
934
954
  writeFileSync2(COMPOSE_PATH, content, "utf-8");
935
- writeFileSync2(COMPOSE_TEST_PATH, TEST_COMPOSE_CONTENT, "utf-8");
955
+ writeFileSync2(COMPOSE_TEST_PATH, generateTestComposeFile(config), "utf-8");
936
956
  }
937
957
 
938
958
  // src/commands/connect.ts
@@ -2836,10 +2856,10 @@ function findFreeSlot(dataDir, cfg) {
2836
2856
  }
2837
2857
  return null;
2838
2858
  }
2839
- function createSlotDirs(slotDataPath) {
2859
+ function createSlotDirs(slotDataPath, vaultNames = ["default"]) {
2840
2860
  const dirs = [
2841
2861
  "notes",
2842
- join7("vaults", "personal"),
2862
+ ...vaultNames.map((name) => join7("vaults", name)),
2843
2863
  "registry",
2844
2864
  "workspaces",
2845
2865
  "sessions",
@@ -2878,7 +2898,8 @@ async function preSeedNotesDir(dataDir, slotDataPath) {
2878
2898
  ]);
2879
2899
  }
2880
2900
  }
2881
- function buildComposeEnv(runtime, ports, slotDataPath) {
2901
+ function buildComposeEnv(runtime, ports, slotDataPath, defaultVaultName = "default") {
2902
+ const vaultPortEnvVar = `VAULT_REST_PORT_${defaultVaultName.toUpperCase().replace(/-/g, "_")}`;
2882
2903
  return {
2883
2904
  ...process.env,
2884
2905
  HORUS_RUNTIME: runtime.name,
@@ -2891,7 +2912,7 @@ function buildComposeEnv(runtime, ports, slotDataPath) {
2891
2912
  FORGE_PORT: String(ports.forge),
2892
2913
  VAULT_MCP_PORT: String(ports.vault_mcp),
2893
2914
  VAULT_ROUTER_PORT: String(ports.vault_router),
2894
- VAULT_REST_PORT_PERSONAL: String(ports.vault_svc),
2915
+ [vaultPortEnvVar]: String(ports.vault_svc),
2895
2916
  TYPESENSE_PORT: String(ports.typesense),
2896
2917
  UI_PORT: String(ports.ui),
2897
2918
  // TEST_PORT_* vars for overlay reference (harmless duplicates after above fix)
@@ -2904,8 +2925,8 @@ function buildComposeEnv(runtime, ports, slotDataPath) {
2904
2925
  TEST_PORT_UI: String(ports.ui)
2905
2926
  };
2906
2927
  }
2907
- async function composeUp(runtime, projectName2, ports, slotDataPath) {
2908
- const env = buildComposeEnv(runtime, ports, slotDataPath);
2928
+ async function composeUp(runtime, projectName2, ports, slotDataPath, defaultVaultName = "default") {
2929
+ const env = buildComposeEnv(runtime, ports, slotDataPath, defaultVaultName);
2909
2930
  const result = await execa3(
2910
2931
  runtime.name,
2911
2932
  [
@@ -2928,8 +2949,8 @@ ${result.stderr}`
2928
2949
  );
2929
2950
  }
2930
2951
  }
2931
- async function composeDown(runtime, projectName2, ports, slotDataPath) {
2932
- const env = buildComposeEnv(runtime, ports, slotDataPath);
2952
+ async function composeDown(runtime, projectName2, ports, slotDataPath, defaultVaultName = "default") {
2953
+ const env = buildComposeEnv(runtime, ports, slotDataPath, defaultVaultName);
2933
2954
  await execa3(
2934
2955
  runtime.name,
2935
2956
  ["compose", "-p", projectName2, "down", "--volumes", "--remove-orphans"],
@@ -3016,6 +3037,9 @@ testEnvCommand.command("acquire").description("Start a shadow stack on alternate
3016
3037
  const config = loadConfig();
3017
3038
  const dataDir = config.data_dir;
3018
3039
  const testCfg = loadTestEnvConfig(dataDir);
3040
+ const vaultNames = Object.keys(config.vaults).sort();
3041
+ const defaultVaultEntry = Object.entries(config.vaults).find(([, v]) => v.default);
3042
+ const defaultVaultName = defaultVaultEntry?.[0] ?? vaultNames[0] ?? "default";
3019
3043
  const spinner = ora8("Detecting runtime...").start();
3020
3044
  let runtime;
3021
3045
  try {
@@ -3037,7 +3061,7 @@ testEnvCommand.command("acquire").description("Start a shadow stack on alternate
3037
3061
  const slotDataPath = getSlotDataPath(dataDir, slot);
3038
3062
  const project = projectName(slot);
3039
3063
  const dirSpinner = ora8(`Creating slot-${slot} data directories...`).start();
3040
- createSlotDirs(slotDataPath);
3064
+ createSlotDirs(slotDataPath, vaultNames);
3041
3065
  dirSpinner.succeed(`Data directory: ${chalk10.dim(slotDataPath)}`);
3042
3066
  const seedSpinner = ora8("Pre-seeding notes directory...").start();
3043
3067
  try {
@@ -3058,7 +3082,7 @@ testEnvCommand.command("acquire").description("Start a shadow stack on alternate
3058
3082
  });
3059
3083
  const upSpinner = ora8(`Starting shadow stack (project ${chalk10.cyan(project)})...`).start();
3060
3084
  try {
3061
- await composeUp(runtime, project, ports, slotDataPath);
3085
+ await composeUp(runtime, project, ports, slotDataPath, defaultVaultName);
3062
3086
  upSpinner.succeed(`Shadow stack started`);
3063
3087
  } catch (error) {
3064
3088
  upSpinner.fail("Failed to start shadow stack");
@@ -3077,7 +3101,7 @@ testEnvCommand.command("acquire").description("Start a shadow stack on alternate
3077
3101
  healthSpinner.succeed("All services healthy");
3078
3102
  } catch (error) {
3079
3103
  healthSpinner.fail("Health check failed");
3080
- await composeDown(runtime, project, ports, slotDataPath);
3104
+ await composeDown(runtime, project, ports, slotDataPath, defaultVaultName);
3081
3105
  removeLock(dataDir, slot);
3082
3106
  removeSlotDirs(slotDataPath);
3083
3107
  console.error(error.message);
@@ -3113,6 +3137,9 @@ testEnvCommand.command("release").description("Tear down a shadow stack and remo
3113
3137
  const config = loadConfig();
3114
3138
  const dataDir = config.data_dir;
3115
3139
  const testCfg = loadTestEnvConfig(dataDir);
3140
+ const vaultNames = Object.keys(config.vaults).sort();
3141
+ const defaultVaultEntry = Object.entries(config.vaults).find(([, v]) => v.default);
3142
+ const defaultVaultName = defaultVaultEntry?.[0] ?? vaultNames[0] ?? "default";
3116
3143
  let slot;
3117
3144
  if (opts.slot !== void 0) {
3118
3145
  slot = parseInt(opts.slot, 10);
@@ -3141,7 +3168,7 @@ testEnvCommand.command("release").description("Tear down a shadow stack and remo
3141
3168
  }
3142
3169
  const downSpinner = ora8(`Stopping ${chalk10.cyan(project)}...`).start();
3143
3170
  try {
3144
- await composeDown(runtime, project, ports, slotDataPath);
3171
+ await composeDown(runtime, project, ports, slotDataPath, defaultVaultName);
3145
3172
  downSpinner.succeed("Shadow stack stopped");
3146
3173
  } catch {
3147
3174
  downSpinner.warn("Failed to stop cleanly (continuing cleanup)");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arkhera30/cli",
3
- "version": "0.3.5",
3
+ "version": "0.3.7",
4
4
  "description": "CLI for managing the Horus AI development stack",
5
5
  "type": "module",
6
6
  "bin": {