@arkhera30/cli 0.3.11 → 0.3.15
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 +65 -26
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -243,6 +243,8 @@ function generateEnv(config) {
|
|
|
243
243
|
`VAULT_ROUTER_PORT=${config.ports.vault_router}`,
|
|
244
244
|
`FORGE_PORT=${config.ports.forge}`,
|
|
245
245
|
`TYPESENSE_PORT=${config.ports.typesense}`,
|
|
246
|
+
`NEO4J_HTTP_PORT=${config.ports.neo4j_http}`,
|
|
247
|
+
`NEO4J_BOLT_PORT=${config.ports.neo4j_bolt}`,
|
|
246
248
|
"",
|
|
247
249
|
"# Search",
|
|
248
250
|
`TYPESENSE_API_KEY=${config.search.api_key}`,
|
|
@@ -611,9 +613,14 @@ var ANVIL_SERVICE = ` # \u2500\u2500 Anvil \u2500\u2500\u2500\u2500\u2500\u2500
|
|
|
611
613
|
- TYPESENSE_HOST=typesense
|
|
612
614
|
- TYPESENSE_PORT=8108
|
|
613
615
|
- TYPESENSE_API_KEY=\${TYPESENSE_API_KEY:-horus-local-key}
|
|
616
|
+
- NEO4J_URI=bolt://neo4j:7687
|
|
617
|
+
- NEO4J_USER=neo4j
|
|
618
|
+
- NEO4J_PASSWORD=horus-neo4j
|
|
614
619
|
depends_on:
|
|
615
620
|
typesense:
|
|
616
621
|
condition: service_healthy
|
|
622
|
+
neo4j:
|
|
623
|
+
condition: service_healthy
|
|
617
624
|
networks:
|
|
618
625
|
- horus-net
|
|
619
626
|
restart: unless-stopped
|
|
@@ -691,6 +698,38 @@ var FORGE_SERVICE = ` # \u2500\u2500 Forge \u2500\u2500\u2500\u2500\u2500\u2500
|
|
|
691
698
|
timeout: 5s
|
|
692
699
|
start_period: 60s
|
|
693
700
|
retries: 3`;
|
|
701
|
+
var NEO4J_SERVICE = ` # \u2500\u2500 Neo4j \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
702
|
+
# Graph database for relationship-aware knowledge queries.
|
|
703
|
+
neo4j:
|
|
704
|
+
image: neo4j:5-community
|
|
705
|
+
ports:
|
|
706
|
+
- "\${NEO4J_HTTP_PORT:-7474}:7474"
|
|
707
|
+
- "\${NEO4J_BOLT_PORT:-7687}:7687"
|
|
708
|
+
volumes:
|
|
709
|
+
- neo4j-data:/data
|
|
710
|
+
- neo4j-logs:/logs
|
|
711
|
+
environment:
|
|
712
|
+
- NEO4J_AUTH=neo4j/horus-neo4j
|
|
713
|
+
- NEO4J_server_memory_heap_initial__size=256m
|
|
714
|
+
- NEO4J_server_memory_heap_max__size=512m
|
|
715
|
+
- NEO4J_server_memory_pagecache_size=256m
|
|
716
|
+
- NEO4J_PLUGINS=[]
|
|
717
|
+
networks:
|
|
718
|
+
- horus-net
|
|
719
|
+
restart: unless-stopped
|
|
720
|
+
stop_grace_period: 30s
|
|
721
|
+
deploy:
|
|
722
|
+
resources:
|
|
723
|
+
limits:
|
|
724
|
+
memory: 1g
|
|
725
|
+
reservations:
|
|
726
|
+
memory: 512m
|
|
727
|
+
healthcheck:
|
|
728
|
+
test: ["CMD", "wget", "--spider", "-q", "http://localhost:7474"]
|
|
729
|
+
interval: 30s
|
|
730
|
+
timeout: 10s
|
|
731
|
+
start_period: 60s
|
|
732
|
+
retries: 3`;
|
|
694
733
|
var TYPESENSE_SERVICE = ` # \u2500\u2500 Typesense \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
695
734
|
# Full-text and vector search engine for unified Horus Search.
|
|
696
735
|
typesense:
|
|
@@ -811,6 +850,14 @@ services:
|
|
|
811
850
|
horus-ui:
|
|
812
851
|
ports:
|
|
813
852
|
- "\${TEST_PORT_UI:-9260}:8400"
|
|
853
|
+
|
|
854
|
+
neo4j:
|
|
855
|
+
ports:
|
|
856
|
+
- "\${TEST_PORT_NEO4J_HTTP:-9474}:7474"
|
|
857
|
+
- "\${TEST_PORT_NEO4J_BOLT:-9687}:7687"
|
|
858
|
+
volumes:
|
|
859
|
+
- "\${TEST_DATA_PATH:-/tmp/horus-test}/neo4j-data:/data"
|
|
860
|
+
- "\${TEST_DATA_PATH:-/tmp/horus-test}/neo4j-logs:/logs"
|
|
814
861
|
`;
|
|
815
862
|
}
|
|
816
863
|
function generateComposeFile(config, runtime) {
|
|
@@ -844,9 +891,14 @@ function generateComposeFile(config, runtime) {
|
|
|
844
891
|
- TYPESENSE_HOST=typesense
|
|
845
892
|
- TYPESENSE_PORT=8108
|
|
846
893
|
- TYPESENSE_API_KEY=\${TYPESENSE_API_KEY:-horus-local-key}
|
|
894
|
+
- NEO4J_URI=bolt://neo4j:7687
|
|
895
|
+
- NEO4J_USER=neo4j
|
|
896
|
+
- NEO4J_PASSWORD=horus-neo4j
|
|
847
897
|
depends_on:
|
|
848
898
|
typesense:
|
|
849
899
|
condition: service_healthy
|
|
900
|
+
neo4j:
|
|
901
|
+
condition: service_healthy
|
|
850
902
|
networks:
|
|
851
903
|
- horus-net
|
|
852
904
|
restart: unless-stopped
|
|
@@ -924,7 +976,11 @@ ${vaultRouterDependsOn}
|
|
|
924
976
|
timeout: 5s
|
|
925
977
|
start_period: 30s
|
|
926
978
|
retries: 3`;
|
|
927
|
-
const vaultVolumeEntries =
|
|
979
|
+
const vaultVolumeEntries = [
|
|
980
|
+
...vaultEntries.map(([name]) => ` vault-${name}-workspace:`),
|
|
981
|
+
" neo4j-data:",
|
|
982
|
+
" neo4j-logs:"
|
|
983
|
+
].join("\n");
|
|
928
984
|
const sections = [
|
|
929
985
|
"# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
930
986
|
"# Horus \u2014 Generated Docker Compose",
|
|
@@ -943,6 +999,8 @@ ${vaultRouterDependsOn}
|
|
|
943
999
|
"",
|
|
944
1000
|
FORGE_SERVICE,
|
|
945
1001
|
"",
|
|
1002
|
+
NEO4J_SERVICE,
|
|
1003
|
+
"",
|
|
946
1004
|
TYPESENSE_SERVICE,
|
|
947
1005
|
"",
|
|
948
1006
|
...config.enable_ui !== false ? [HORUS_UI_SERVICE, ""] : [],
|
|
@@ -1025,16 +1083,6 @@ function mergeAndWriteConfig(configPath, mcpServers) {
|
|
|
1025
1083
|
mkdirSync2(dir, { recursive: true });
|
|
1026
1084
|
writeFileSync3(configPath, JSON.stringify(existing, null, 2) + "\n", "utf-8");
|
|
1027
1085
|
}
|
|
1028
|
-
function getMcpRemoteWrapperPath() {
|
|
1029
|
-
return join2(homedir3(), ".forge", "bin", "mcp-remote-wrapper");
|
|
1030
|
-
}
|
|
1031
|
-
function buildStdioServers(config, wrapperPath, host) {
|
|
1032
|
-
return {
|
|
1033
|
-
anvil: { command: wrapperPath, args: [`http://${host}:${config.ports.anvil}/mcp`, "--transport", "http-only"] },
|
|
1034
|
-
vault: { command: wrapperPath, args: [`http://${host}:${config.ports.vault_mcp}/mcp`, "--transport", "http-only"] },
|
|
1035
|
-
forge: { command: wrapperPath, args: [`http://${host}:${config.ports.forge}/mcp`, "--transport", "http-only"] }
|
|
1036
|
-
};
|
|
1037
|
-
}
|
|
1038
1086
|
async function isClaudeCliAvailable() {
|
|
1039
1087
|
try {
|
|
1040
1088
|
const result = await execa2("claude", ["--version"], { reject: false });
|
|
@@ -1047,7 +1095,7 @@ async function registerWithClaudeCode(mcpServers) {
|
|
|
1047
1095
|
const registered = [];
|
|
1048
1096
|
const failed = [];
|
|
1049
1097
|
for (const [name, entry] of Object.entries(mcpServers)) {
|
|
1050
|
-
const baseUrl = entry.url.replace(/\/sse$/, "");
|
|
1098
|
+
const baseUrl = entry.url.replace(/\/(mcp|sse)$/, "");
|
|
1051
1099
|
await execa2("claude", ["mcp", "remove", "--scope", "user", name], { reject: false });
|
|
1052
1100
|
const result = await execa2(
|
|
1053
1101
|
"claude",
|
|
@@ -1123,26 +1171,17 @@ function printNextSteps(targets) {
|
|
|
1123
1171
|
}
|
|
1124
1172
|
async function runConnect(config, runtime, targets, host = "localhost") {
|
|
1125
1173
|
const httpServers = {
|
|
1126
|
-
anvil: { url: `http://${host}:${config.ports.anvil}/
|
|
1127
|
-
vault: { url: `http://${host}:${config.ports.vault_mcp}/
|
|
1128
|
-
forge: { url: `http://${host}:${config.ports.forge}/
|
|
1174
|
+
anvil: { url: `http://${host}:${config.ports.anvil}/mcp` },
|
|
1175
|
+
vault: { url: `http://${host}:${config.ports.vault_mcp}/mcp` },
|
|
1176
|
+
forge: { url: `http://${host}:${config.ports.forge}/mcp` }
|
|
1129
1177
|
};
|
|
1130
1178
|
const configured = [];
|
|
1131
1179
|
for (const target of targets) {
|
|
1132
1180
|
if (target === "claude-desktop") {
|
|
1133
1181
|
const desktopSpinner = ora(`Configuring ${chalk.cyan("claude-desktop")}...`).start();
|
|
1134
|
-
const wrapperPath = getMcpRemoteWrapperPath();
|
|
1135
|
-
if (!existsSync4(wrapperPath)) {
|
|
1136
|
-
desktopSpinner.fail("mcp-remote-wrapper not found");
|
|
1137
|
-
console.log(chalk.dim(`Expected at: ${wrapperPath}`));
|
|
1138
|
-
console.log(chalk.dim("Install it with: npx --yes mcp-remote --help"));
|
|
1139
|
-
console.log(chalk.dim("Then place the wrapper script at the path above."));
|
|
1140
|
-
continue;
|
|
1141
|
-
}
|
|
1142
1182
|
try {
|
|
1143
|
-
const stdioServers = buildStdioServers(config, wrapperPath, host);
|
|
1144
1183
|
const configPath = getConfigPath(target);
|
|
1145
|
-
mergeAndWriteConfig(configPath,
|
|
1184
|
+
mergeAndWriteConfig(configPath, httpServers);
|
|
1146
1185
|
desktopSpinner.succeed(`Configured ${chalk.cyan("claude-desktop")} \u2014 ${chalk.dim(configPath)}`);
|
|
1147
1186
|
configured.push(target);
|
|
1148
1187
|
} catch (error) {
|
|
@@ -1170,7 +1209,7 @@ async function runConnect(config, runtime, targets, host = "localhost") {
|
|
|
1170
1209
|
} else {
|
|
1171
1210
|
cliSpinner.warn("claude CLI not found on PATH \u2014 register manually:");
|
|
1172
1211
|
for (const [name, entry] of Object.entries(httpServers)) {
|
|
1173
|
-
const baseUrl = entry.url.replace(/\/sse$/, "");
|
|
1212
|
+
const baseUrl = entry.url.replace(/\/(mcp|sse)$/, "");
|
|
1174
1213
|
console.log(
|
|
1175
1214
|
chalk.dim(` claude mcp add --transport http --scope user ${name} ${baseUrl}`)
|
|
1176
1215
|
);
|