@olorehq/olore 0.3.0 → 0.3.2
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/cli.js +127 -27
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -25,7 +25,8 @@ import fs from "fs-extra";
|
|
|
25
25
|
import * as tar from "tar";
|
|
26
26
|
|
|
27
27
|
// src/core/constants.ts
|
|
28
|
-
var REGISTRY_URL = "https://
|
|
28
|
+
var REGISTRY_URL = "https://github.com/olorehq/olore/releases/download/registry/registry.json";
|
|
29
|
+
var REGISTRY_FALLBACK_URL = "https://olore.dev/registry";
|
|
29
30
|
var DOWNLOAD_TIMEOUT = 6e4;
|
|
30
31
|
var USER_AGENT = "olore-cli/0.1.0";
|
|
31
32
|
|
|
@@ -725,29 +726,48 @@ function formatLibraryName(name) {
|
|
|
725
726
|
if (specialNames[name]) return specialNames[name];
|
|
726
727
|
return name.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
727
728
|
}
|
|
728
|
-
|
|
729
|
-
const
|
|
730
|
-
|
|
731
|
-
|
|
729
|
+
function resolvePackages(requested, installed) {
|
|
730
|
+
const matched = [];
|
|
731
|
+
const notFound = [];
|
|
732
|
+
for (const req of requested) {
|
|
733
|
+
const normalized = req.replace(/^olore-/, "");
|
|
734
|
+
let found = installed.find((pkg) => pkg.name === normalized);
|
|
735
|
+
if (!found && normalized.includes("@")) {
|
|
736
|
+
const [name, version2] = normalized.split("@");
|
|
737
|
+
found = installed.find((pkg) => pkg.name === name && pkg.version === version2);
|
|
738
|
+
}
|
|
739
|
+
if (!found) {
|
|
740
|
+
found = installed.find((pkg) => `${pkg.name}-${pkg.version}` === normalized);
|
|
741
|
+
}
|
|
742
|
+
if (found) {
|
|
743
|
+
if (!matched.includes(found)) {
|
|
744
|
+
matched.push(found);
|
|
745
|
+
}
|
|
746
|
+
} else {
|
|
747
|
+
notFound.push(req);
|
|
748
|
+
}
|
|
732
749
|
}
|
|
750
|
+
return { matched, notFound };
|
|
751
|
+
}
|
|
752
|
+
function buildInjectedContent(packages) {
|
|
733
753
|
const rows = packages.map((pkg) => {
|
|
734
754
|
const library = formatLibraryName(pkg.name);
|
|
735
755
|
const version2 = pkg.version !== "latest" ? ` ${pkg.version}` : "";
|
|
736
|
-
const skillCommand =
|
|
756
|
+
const skillCommand = `olore-${pkg.name}-${pkg.version}`;
|
|
737
757
|
return `| ${library}${version2} | \`${skillCommand}\` |`;
|
|
738
758
|
});
|
|
739
759
|
const lines = [
|
|
740
760
|
MARKER_START,
|
|
741
761
|
"## Documentation Reference",
|
|
742
762
|
"",
|
|
743
|
-
"Use these
|
|
763
|
+
"Use these skills to access up-to-date documentation. Your training data may be outdated.",
|
|
744
764
|
"",
|
|
745
|
-
"| Library | Skill
|
|
746
|
-
"
|
|
765
|
+
"| Library | Skill |",
|
|
766
|
+
"|---------|-------|",
|
|
747
767
|
...rows,
|
|
748
768
|
MARKER_END
|
|
749
769
|
];
|
|
750
|
-
return
|
|
770
|
+
return lines.join("\n");
|
|
751
771
|
}
|
|
752
772
|
function smartMerge(filePath, injectedContent) {
|
|
753
773
|
if (!fs6.existsSync(filePath)) {
|
|
@@ -782,7 +802,7 @@ function removeSection(filePath) {
|
|
|
782
802
|
}
|
|
783
803
|
return true;
|
|
784
804
|
}
|
|
785
|
-
async function inject(options) {
|
|
805
|
+
async function inject(packages, options) {
|
|
786
806
|
const cwd = process.cwd();
|
|
787
807
|
if (options.remove) {
|
|
788
808
|
const filesRemoved = [];
|
|
@@ -809,8 +829,7 @@ async function inject(options) {
|
|
|
809
829
|
}
|
|
810
830
|
return;
|
|
811
831
|
}
|
|
812
|
-
|
|
813
|
-
if (count === 0) {
|
|
832
|
+
if (packages.length === 0) {
|
|
814
833
|
if (options.json) {
|
|
815
834
|
const result = {
|
|
816
835
|
packagesFound: 0,
|
|
@@ -821,10 +840,31 @@ async function inject(options) {
|
|
|
821
840
|
console.log(JSON.stringify(result, null, 2));
|
|
822
841
|
return;
|
|
823
842
|
}
|
|
824
|
-
console.log(pc3.yellow("No
|
|
825
|
-
console.log(pc3.gray("
|
|
843
|
+
console.log(pc3.yellow("No packages specified."));
|
|
844
|
+
console.log(pc3.gray("Usage: olore inject <package1> <package2> ..."));
|
|
845
|
+
console.log(pc3.gray("Example: olore inject nextjs prisma zod"));
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
const installed = await getInstalledPackages();
|
|
849
|
+
const { matched, notFound } = resolvePackages(packages, installed);
|
|
850
|
+
if (notFound.length > 0) {
|
|
851
|
+
console.log(pc3.yellow(`Not installed: ${notFound.join(", ")}`));
|
|
852
|
+
console.log(pc3.gray("Run olore install <package> first."));
|
|
853
|
+
if (matched.length === 0) return;
|
|
854
|
+
}
|
|
855
|
+
if (matched.length === 0) {
|
|
856
|
+
if (options.json) {
|
|
857
|
+
const result = {
|
|
858
|
+
packagesFound: 0,
|
|
859
|
+
packagesInjected: 0,
|
|
860
|
+
filesWritten: [],
|
|
861
|
+
removed: false
|
|
862
|
+
};
|
|
863
|
+
console.log(JSON.stringify(result, null, 2));
|
|
864
|
+
}
|
|
826
865
|
return;
|
|
827
866
|
}
|
|
867
|
+
const content = buildInjectedContent(matched);
|
|
828
868
|
const filesWritten = [];
|
|
829
869
|
for (const fileName of TARGET_FILES) {
|
|
830
870
|
const filePath = path6.join(cwd, fileName);
|
|
@@ -833,8 +873,8 @@ async function inject(options) {
|
|
|
833
873
|
}
|
|
834
874
|
if (options.json) {
|
|
835
875
|
const result = {
|
|
836
|
-
packagesFound:
|
|
837
|
-
packagesInjected:
|
|
876
|
+
packagesFound: installed.length,
|
|
877
|
+
packagesInjected: matched.length,
|
|
838
878
|
filesWritten,
|
|
839
879
|
removed: false
|
|
840
880
|
};
|
|
@@ -843,7 +883,7 @@ async function inject(options) {
|
|
|
843
883
|
}
|
|
844
884
|
console.log(
|
|
845
885
|
pc3.green(
|
|
846
|
-
`Injected ${
|
|
886
|
+
`Injected ${matched.length} package${matched.length === 1 ? "" : "s"} into: ${filesWritten.join(", ")}`
|
|
847
887
|
)
|
|
848
888
|
);
|
|
849
889
|
console.log(pc3.gray("Run olore inject --remove to clean up."));
|
|
@@ -886,8 +926,23 @@ async function fetchWithTimeout(url, timeout = DOWNLOAD_TIMEOUT) {
|
|
|
886
926
|
clearTimeout(timeoutId);
|
|
887
927
|
}
|
|
888
928
|
}
|
|
889
|
-
|
|
890
|
-
|
|
929
|
+
var cachedRegistry = null;
|
|
930
|
+
async function fetchCombinedRegistry() {
|
|
931
|
+
if (cachedRegistry) {
|
|
932
|
+
return cachedRegistry;
|
|
933
|
+
}
|
|
934
|
+
try {
|
|
935
|
+
const response2 = await fetchWithTimeout(REGISTRY_URL);
|
|
936
|
+
if (response2.ok) {
|
|
937
|
+
const data = await response2.json();
|
|
938
|
+
if (data.version === 2) {
|
|
939
|
+
cachedRegistry = data;
|
|
940
|
+
return cachedRegistry;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
} catch {
|
|
944
|
+
}
|
|
945
|
+
const url = `${REGISTRY_FALLBACK_URL}/index.json`;
|
|
891
946
|
const response = await fetchWithTimeout(url);
|
|
892
947
|
if (response.status === 404) {
|
|
893
948
|
throw new RegistryError("Registry not found", "NOT_FOUND");
|
|
@@ -895,15 +950,58 @@ async function fetchPackageIndex() {
|
|
|
895
950
|
if (!response.ok) {
|
|
896
951
|
throw new RegistryError(`Failed to fetch registry: ${response.status}`, "NETWORK_ERROR");
|
|
897
952
|
}
|
|
953
|
+
let index;
|
|
898
954
|
try {
|
|
899
|
-
|
|
900
|
-
return data;
|
|
955
|
+
index = await response.json();
|
|
901
956
|
} catch {
|
|
902
957
|
throw new RegistryError("Invalid registry response", "INVALID_RESPONSE");
|
|
903
958
|
}
|
|
959
|
+
const packages = {};
|
|
960
|
+
for (const [name, entry] of Object.entries(index.packages)) {
|
|
961
|
+
packages[name] = {
|
|
962
|
+
description: entry.description,
|
|
963
|
+
latest: entry.latest,
|
|
964
|
+
versions: {}
|
|
965
|
+
// populated on demand in fetchPackageVersions
|
|
966
|
+
};
|
|
967
|
+
}
|
|
968
|
+
cachedRegistry = {
|
|
969
|
+
version: 2,
|
|
970
|
+
updated: index.updated,
|
|
971
|
+
packages
|
|
972
|
+
};
|
|
973
|
+
return cachedRegistry;
|
|
974
|
+
}
|
|
975
|
+
async function fetchPackageIndex() {
|
|
976
|
+
const combined = await fetchCombinedRegistry();
|
|
977
|
+
const packages = {};
|
|
978
|
+
for (const [name, entry] of Object.entries(combined.packages)) {
|
|
979
|
+
packages[name] = {
|
|
980
|
+
description: entry.description,
|
|
981
|
+
latest: entry.latest,
|
|
982
|
+
versions: Object.keys(entry.versions).length > 0 ? Object.keys(entry.versions) : [entry.latest]
|
|
983
|
+
};
|
|
984
|
+
}
|
|
985
|
+
return {
|
|
986
|
+
version: combined.version,
|
|
987
|
+
updated: combined.updated,
|
|
988
|
+
packages
|
|
989
|
+
};
|
|
904
990
|
}
|
|
905
991
|
async function fetchPackageVersions(name) {
|
|
906
|
-
const
|
|
992
|
+
const combined = await fetchCombinedRegistry();
|
|
993
|
+
const entry = combined.packages[name];
|
|
994
|
+
if (!entry) {
|
|
995
|
+
throw new RegistryError(`Package "${name}" not found in registry`, "NOT_FOUND");
|
|
996
|
+
}
|
|
997
|
+
if (Object.keys(entry.versions).length > 0) {
|
|
998
|
+
return {
|
|
999
|
+
name,
|
|
1000
|
+
description: entry.description,
|
|
1001
|
+
versions: entry.versions
|
|
1002
|
+
};
|
|
1003
|
+
}
|
|
1004
|
+
const url = `${REGISTRY_FALLBACK_URL}/packages/${name}.json`;
|
|
907
1005
|
const response = await fetchWithTimeout(url);
|
|
908
1006
|
if (response.status === 404) {
|
|
909
1007
|
throw new RegistryError(`Package "${name}" not found in registry`, "NOT_FOUND");
|
|
@@ -913,7 +1011,9 @@ async function fetchPackageVersions(name) {
|
|
|
913
1011
|
}
|
|
914
1012
|
try {
|
|
915
1013
|
const data = await response.json();
|
|
916
|
-
|
|
1014
|
+
const versions = data;
|
|
1015
|
+
entry.versions = versions.versions;
|
|
1016
|
+
return versions;
|
|
917
1017
|
} catch {
|
|
918
1018
|
throw new RegistryError("Invalid package response", "INVALID_RESPONSE");
|
|
919
1019
|
}
|
|
@@ -941,7 +1041,7 @@ import pc4 from "picocolors";
|
|
|
941
1041
|
// package.json
|
|
942
1042
|
var package_default = {
|
|
943
1043
|
name: "@olorehq/olore",
|
|
944
|
-
version: "0.3.
|
|
1044
|
+
version: "0.3.2",
|
|
945
1045
|
description: "Universal documentation for any AI coding agent",
|
|
946
1046
|
keywords: [
|
|
947
1047
|
"ai",
|
|
@@ -1773,9 +1873,9 @@ program.command("prune").description("Remove dangling symlinks, orphaned package
|
|
|
1773
1873
|
process.exit(1);
|
|
1774
1874
|
}
|
|
1775
1875
|
});
|
|
1776
|
-
program.command("inject").description("Inject documentation
|
|
1876
|
+
program.command("inject [packages...]").description("Inject documentation reference into AGENTS.md and CLAUDE.md").option("--remove", "Remove injected content from project files").option("--json", "Output as JSON").action(async (packages, options) => {
|
|
1777
1877
|
try {
|
|
1778
|
-
await inject(options);
|
|
1878
|
+
await inject(packages, options);
|
|
1779
1879
|
} catch (error) {
|
|
1780
1880
|
console.error(pc12.red(`Error: ${error.message}`));
|
|
1781
1881
|
process.exit(1);
|