@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.
Files changed (2) hide show
  1. package/dist/cli.js +127 -27
  2. 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://olore.dev/registry";
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
- async function buildInjectedContent() {
729
- const packages = await getInstalledPackages();
730
- if (packages.length === 0) {
731
- return { content: "", count: 0 };
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 = `/olore-${pkg.name}-${pkg.version}`;
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 skill commands to access up-to-date documentation. Your training data may be outdated.",
763
+ "Use these skills to access up-to-date documentation. Your training data may be outdated.",
744
764
  "",
745
- "| Library | Skill Command |",
746
- "|---------|---------------|",
765
+ "| Library | Skill |",
766
+ "|---------|-------|",
747
767
  ...rows,
748
768
  MARKER_END
749
769
  ];
750
- return { content: lines.join("\n"), count: packages.length };
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
- const { content, count } = await buildInjectedContent();
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 installed packages found."));
825
- console.log(pc3.gray("Run olore install <package> to install documentation packages."));
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: count,
837
- packagesInjected: count,
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 ${count} package${count === 1 ? "" : "s"} into: ${filesWritten.join(", ")}`
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
- async function fetchPackageIndex() {
890
- const url = `${REGISTRY_URL}/index.json`;
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
- const data = await response.json();
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 url = `${REGISTRY_URL}/packages/${name}.json`;
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
- return data;
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.0",
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 skill reference table into AGENTS.md and CLAUDE.md").option("--remove", "Remove injected content from project files").option("--json", "Output as JSON").action(async (options) => {
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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@olorehq/olore",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Universal documentation for any AI coding agent",
5
5
  "keywords": [
6
6
  "ai",