@arkhera30/cli 0.3.6 → 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.
- package/dist/index.js +39 -19
- 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
|
|
@@ -649,9 +655,14 @@ var FORGE_SERVICE = ` # \u2500\u2500 Forge \u2500\u2500\u2500\u2500\u2500\u2500
|
|
|
649
655
|
- FORGE_HOST_FORGE_URL=http://localhost:\${FORGE_PORT:-8200}
|
|
650
656
|
- FORGE_SCAN_PATHS=\${FORGE_SCAN_PATHS:-/data/repos}
|
|
651
657
|
- GITHUB_TOKEN=\${GITHUB_TOKEN:-}
|
|
658
|
+
- TYPESENSE_HOST=typesense
|
|
659
|
+
- TYPESENSE_PORT=8108
|
|
660
|
+
- TYPESENSE_API_KEY=\${TYPESENSE_API_KEY:-horus-local-key}
|
|
652
661
|
depends_on:
|
|
653
662
|
anvil:
|
|
654
663
|
condition: service_healthy
|
|
664
|
+
typesense:
|
|
665
|
+
condition: service_healthy
|
|
655
666
|
vault-router:
|
|
656
667
|
condition: service_healthy
|
|
657
668
|
networks:
|
|
@@ -731,7 +742,11 @@ var HORUS_UI_SERVICE = ` # \u2500\u2500 Horus UI \u2500\u2500\u2500\u2500\u2500
|
|
|
731
742
|
timeout: 5s
|
|
732
743
|
start_period: 30s
|
|
733
744
|
retries: 3`;
|
|
734
|
-
|
|
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
|
|
735
750
|
# Horus \u2014 Shadow Stack Overlay for Integration Testing
|
|
736
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
|
|
737
752
|
# Usage (managed by \`horus test-env acquire\`):
|
|
@@ -744,9 +759,6 @@ var TEST_COMPOSE_CONTENT = `# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u
|
|
|
744
759
|
#
|
|
745
760
|
# All TEST_PORT_* and TEST_DATA_PATH are set by \`horus test-env acquire\`.
|
|
746
761
|
# Slot 0 defaults: ports 9100-9399, data at ~/Horus/data/test-env/slot-0/
|
|
747
|
-
#
|
|
748
|
-
# NOTE: vault-personal is assumed as the primary vault name. If your config
|
|
749
|
-
# uses a different vault name, set TEST_VAULT_NAME accordingly.
|
|
750
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
|
|
751
763
|
|
|
752
764
|
services:
|
|
@@ -756,11 +768,11 @@ services:
|
|
|
756
768
|
volumes:
|
|
757
769
|
- "\${TEST_DATA_PATH:-/tmp/horus-test}/notes:/data/notes:rw"
|
|
758
770
|
|
|
759
|
-
vault
|
|
771
|
+
vault-${vaultName}:
|
|
760
772
|
ports:
|
|
761
773
|
- "\${TEST_PORT_VAULT_SVC:-9101}:8000"
|
|
762
774
|
volumes:
|
|
763
|
-
- "\${TEST_DATA_PATH:-/tmp/horus-test}/vaults
|
|
775
|
+
- "\${TEST_DATA_PATH:-/tmp/horus-test}/vaults/${vaultName}:/data/knowledge-repo:rw"
|
|
764
776
|
|
|
765
777
|
vault-router:
|
|
766
778
|
ports:
|
|
@@ -790,6 +802,7 @@ services:
|
|
|
790
802
|
ports:
|
|
791
803
|
- "\${TEST_PORT_UI:-9260}:8400"
|
|
792
804
|
`;
|
|
805
|
+
}
|
|
793
806
|
function generateComposeFile(config, runtime) {
|
|
794
807
|
const vaultEntries = Object.entries(config.vaults).sort(([a], [b]) => a.localeCompare(b));
|
|
795
808
|
const vaultServices = vaultEntries.map(([name, vault], index) => {
|
|
@@ -939,7 +952,7 @@ function installComposeFile(config, runtime) {
|
|
|
939
952
|
ensureHorusDir();
|
|
940
953
|
const content = generateComposeFile(config, runtime);
|
|
941
954
|
writeFileSync2(COMPOSE_PATH, content, "utf-8");
|
|
942
|
-
writeFileSync2(COMPOSE_TEST_PATH,
|
|
955
|
+
writeFileSync2(COMPOSE_TEST_PATH, generateTestComposeFile(config), "utf-8");
|
|
943
956
|
}
|
|
944
957
|
|
|
945
958
|
// src/commands/connect.ts
|
|
@@ -2843,10 +2856,10 @@ function findFreeSlot(dataDir, cfg) {
|
|
|
2843
2856
|
}
|
|
2844
2857
|
return null;
|
|
2845
2858
|
}
|
|
2846
|
-
function createSlotDirs(slotDataPath) {
|
|
2859
|
+
function createSlotDirs(slotDataPath, vaultNames = ["default"]) {
|
|
2847
2860
|
const dirs = [
|
|
2848
2861
|
"notes",
|
|
2849
|
-
join7("vaults",
|
|
2862
|
+
...vaultNames.map((name) => join7("vaults", name)),
|
|
2850
2863
|
"registry",
|
|
2851
2864
|
"workspaces",
|
|
2852
2865
|
"sessions",
|
|
@@ -2885,7 +2898,8 @@ async function preSeedNotesDir(dataDir, slotDataPath) {
|
|
|
2885
2898
|
]);
|
|
2886
2899
|
}
|
|
2887
2900
|
}
|
|
2888
|
-
function buildComposeEnv(runtime, ports, slotDataPath) {
|
|
2901
|
+
function buildComposeEnv(runtime, ports, slotDataPath, defaultVaultName = "default") {
|
|
2902
|
+
const vaultPortEnvVar = `VAULT_REST_PORT_${defaultVaultName.toUpperCase().replace(/-/g, "_")}`;
|
|
2889
2903
|
return {
|
|
2890
2904
|
...process.env,
|
|
2891
2905
|
HORUS_RUNTIME: runtime.name,
|
|
@@ -2898,7 +2912,7 @@ function buildComposeEnv(runtime, ports, slotDataPath) {
|
|
|
2898
2912
|
FORGE_PORT: String(ports.forge),
|
|
2899
2913
|
VAULT_MCP_PORT: String(ports.vault_mcp),
|
|
2900
2914
|
VAULT_ROUTER_PORT: String(ports.vault_router),
|
|
2901
|
-
|
|
2915
|
+
[vaultPortEnvVar]: String(ports.vault_svc),
|
|
2902
2916
|
TYPESENSE_PORT: String(ports.typesense),
|
|
2903
2917
|
UI_PORT: String(ports.ui),
|
|
2904
2918
|
// TEST_PORT_* vars for overlay reference (harmless duplicates after above fix)
|
|
@@ -2911,8 +2925,8 @@ function buildComposeEnv(runtime, ports, slotDataPath) {
|
|
|
2911
2925
|
TEST_PORT_UI: String(ports.ui)
|
|
2912
2926
|
};
|
|
2913
2927
|
}
|
|
2914
|
-
async function composeUp(runtime, projectName2, ports, slotDataPath) {
|
|
2915
|
-
const env = buildComposeEnv(runtime, ports, slotDataPath);
|
|
2928
|
+
async function composeUp(runtime, projectName2, ports, slotDataPath, defaultVaultName = "default") {
|
|
2929
|
+
const env = buildComposeEnv(runtime, ports, slotDataPath, defaultVaultName);
|
|
2916
2930
|
const result = await execa3(
|
|
2917
2931
|
runtime.name,
|
|
2918
2932
|
[
|
|
@@ -2935,8 +2949,8 @@ ${result.stderr}`
|
|
|
2935
2949
|
);
|
|
2936
2950
|
}
|
|
2937
2951
|
}
|
|
2938
|
-
async function composeDown(runtime, projectName2, ports, slotDataPath) {
|
|
2939
|
-
const env = buildComposeEnv(runtime, ports, slotDataPath);
|
|
2952
|
+
async function composeDown(runtime, projectName2, ports, slotDataPath, defaultVaultName = "default") {
|
|
2953
|
+
const env = buildComposeEnv(runtime, ports, slotDataPath, defaultVaultName);
|
|
2940
2954
|
await execa3(
|
|
2941
2955
|
runtime.name,
|
|
2942
2956
|
["compose", "-p", projectName2, "down", "--volumes", "--remove-orphans"],
|
|
@@ -3023,6 +3037,9 @@ testEnvCommand.command("acquire").description("Start a shadow stack on alternate
|
|
|
3023
3037
|
const config = loadConfig();
|
|
3024
3038
|
const dataDir = config.data_dir;
|
|
3025
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";
|
|
3026
3043
|
const spinner = ora8("Detecting runtime...").start();
|
|
3027
3044
|
let runtime;
|
|
3028
3045
|
try {
|
|
@@ -3044,7 +3061,7 @@ testEnvCommand.command("acquire").description("Start a shadow stack on alternate
|
|
|
3044
3061
|
const slotDataPath = getSlotDataPath(dataDir, slot);
|
|
3045
3062
|
const project = projectName(slot);
|
|
3046
3063
|
const dirSpinner = ora8(`Creating slot-${slot} data directories...`).start();
|
|
3047
|
-
createSlotDirs(slotDataPath);
|
|
3064
|
+
createSlotDirs(slotDataPath, vaultNames);
|
|
3048
3065
|
dirSpinner.succeed(`Data directory: ${chalk10.dim(slotDataPath)}`);
|
|
3049
3066
|
const seedSpinner = ora8("Pre-seeding notes directory...").start();
|
|
3050
3067
|
try {
|
|
@@ -3065,7 +3082,7 @@ testEnvCommand.command("acquire").description("Start a shadow stack on alternate
|
|
|
3065
3082
|
});
|
|
3066
3083
|
const upSpinner = ora8(`Starting shadow stack (project ${chalk10.cyan(project)})...`).start();
|
|
3067
3084
|
try {
|
|
3068
|
-
await composeUp(runtime, project, ports, slotDataPath);
|
|
3085
|
+
await composeUp(runtime, project, ports, slotDataPath, defaultVaultName);
|
|
3069
3086
|
upSpinner.succeed(`Shadow stack started`);
|
|
3070
3087
|
} catch (error) {
|
|
3071
3088
|
upSpinner.fail("Failed to start shadow stack");
|
|
@@ -3084,7 +3101,7 @@ testEnvCommand.command("acquire").description("Start a shadow stack on alternate
|
|
|
3084
3101
|
healthSpinner.succeed("All services healthy");
|
|
3085
3102
|
} catch (error) {
|
|
3086
3103
|
healthSpinner.fail("Health check failed");
|
|
3087
|
-
await composeDown(runtime, project, ports, slotDataPath);
|
|
3104
|
+
await composeDown(runtime, project, ports, slotDataPath, defaultVaultName);
|
|
3088
3105
|
removeLock(dataDir, slot);
|
|
3089
3106
|
removeSlotDirs(slotDataPath);
|
|
3090
3107
|
console.error(error.message);
|
|
@@ -3120,6 +3137,9 @@ testEnvCommand.command("release").description("Tear down a shadow stack and remo
|
|
|
3120
3137
|
const config = loadConfig();
|
|
3121
3138
|
const dataDir = config.data_dir;
|
|
3122
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";
|
|
3123
3143
|
let slot;
|
|
3124
3144
|
if (opts.slot !== void 0) {
|
|
3125
3145
|
slot = parseInt(opts.slot, 10);
|
|
@@ -3148,7 +3168,7 @@ testEnvCommand.command("release").description("Tear down a shadow stack and remo
|
|
|
3148
3168
|
}
|
|
3149
3169
|
const downSpinner = ora8(`Stopping ${chalk10.cyan(project)}...`).start();
|
|
3150
3170
|
try {
|
|
3151
|
-
await composeDown(runtime, project, ports, slotDataPath);
|
|
3171
|
+
await composeDown(runtime, project, ports, slotDataPath, defaultVaultName);
|
|
3152
3172
|
downSpinner.succeed("Shadow stack stopped");
|
|
3153
3173
|
} catch {
|
|
3154
3174
|
downSpinner.warn("Failed to stop cleanly (continuing cleanup)");
|