@larkup/cli 0.2.6 → 0.2.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 CHANGED
@@ -12,18 +12,6 @@ import {
12
12
  setActiveServer,
13
13
  trackUsageEvent
14
14
  } from "./chunk-ZJLA4SIG.js";
15
- import {
16
- getInstalledTool,
17
- getInstalledTools,
18
- installTool,
19
- isToolInstalled,
20
- loadTool,
21
- uninstallTool
22
- } from "./chunk-VY6I42DP.js";
23
- import {
24
- getAllTools,
25
- getToolById
26
- } from "./chunk-P5JVXA7X.js";
27
15
  import {
28
16
  __require
29
17
  } from "./chunk-3RG5ZIWI.js";
@@ -34,7 +22,7 @@ import { Command } from "commander";
34
22
  // package.json
35
23
  var package_default = {
36
24
  name: "@larkup/cli",
37
- version: "0.2.6",
25
+ version: "0.2.7",
38
26
  publishConfig: {
39
27
  access: "public"
40
28
  },
@@ -951,12 +939,12 @@ function addChatProviderDependency(dependencies, provider) {
951
939
  }
952
940
 
953
941
  // ../../packages/core/src/generator/generate-server.ts
954
- function lang(path14) {
955
- if (path14.endsWith(".json")) return "json";
956
- if (path14.endsWith(".mjs") || path14.endsWith(".js")) return "javascript";
957
- if (path14.endsWith(".md")) return "markdown";
958
- if (path14.endsWith("Dockerfile")) return "dockerfile";
959
- if (path14.endsWith(".yml") || path14.endsWith(".yaml")) return "yaml";
942
+ function lang(path13) {
943
+ if (path13.endsWith(".json")) return "json";
944
+ if (path13.endsWith(".mjs") || path13.endsWith(".js")) return "javascript";
945
+ if (path13.endsWith(".md")) return "markdown";
946
+ if (path13.endsWith("Dockerfile")) return "dockerfile";
947
+ if (path13.endsWith(".yml") || path13.endsWith(".yaml")) return "yaml";
960
948
  return "text";
961
949
  }
962
950
  function lancedbStore() {
@@ -1415,7 +1403,7 @@ const server = createServer(async (req, res) => {
1415
1403
  <svg class="icon" viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>
1416
1404
  API Reference
1417
1405
  </a>
1418
- <a href="https://github.com/Larkup-AI/larkup-rag" target="_blank" rel="noopener" class="btn btn-outline">
1406
+ <a href="https://github.com/Larkup-AI/larkup" target="_blank" rel="noopener" class="btn btn-outline">
1419
1407
  <svg class="icon" viewBox="0 0 24 24"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
1420
1408
  Larkup Team
1421
1409
  </a>
@@ -1424,7 +1412,7 @@ const server = createServer(async (req, res) => {
1424
1412
  Contact
1425
1413
  </a>
1426
1414
  </div>
1427
- <div class="footer">Built with <a href="https://github.com/Larkup-AI/larkup-rag/buddy-rag" target="_blank" rel="noopener">larkup</a> \xB7 v1.0</div>
1415
+ <div class="footer">Built with <a href="https://github.com/Larkup-AI/larkup/buddy-rag" target="_blank" rel="noopener">larkup</a> \xB7 v1.0</div>
1428
1416
  </div>
1429
1417
  </body>
1430
1418
  </html>\`)
@@ -2273,22 +2261,22 @@ function generateServer(config) {
2273
2261
  { path: "README.md", contents: readme(config, server) }
2274
2262
  ].map((f) => ({ ...f, language: lang(f.path) }));
2275
2263
  try {
2276
- const fs13 = __require("fs");
2277
- const path14 = __require("path");
2278
- const faviconPath = path14.resolve(process.cwd(), "public/favicon2.ico");
2279
- if (fs13.existsSync(faviconPath)) {
2264
+ const fs12 = __require("fs");
2265
+ const path13 = __require("path");
2266
+ const faviconPath = path13.resolve(process.cwd(), "public/favicon2.ico");
2267
+ if (fs12.existsSync(faviconPath)) {
2280
2268
  files.push({
2281
2269
  path: "public/favicon2.ico",
2282
- contents: fs13.readFileSync(faviconPath).toString("base64"),
2270
+ contents: fs12.readFileSync(faviconPath).toString("base64"),
2283
2271
  language: "ico",
2284
2272
  encoding: "base64"
2285
2273
  });
2286
2274
  } else {
2287
- const webFaviconPath = path14.resolve(process.cwd(), "apps/web/public/favicon2.ico");
2288
- if (fs13.existsSync(webFaviconPath)) {
2275
+ const webFaviconPath = path13.resolve(process.cwd(), "apps/web/public/favicon2.ico");
2276
+ if (fs12.existsSync(webFaviconPath)) {
2289
2277
  files.push({
2290
2278
  path: "public/favicon2.ico",
2291
- contents: fs13.readFileSync(webFaviconPath).toString("base64"),
2279
+ contents: fs12.readFileSync(webFaviconPath).toString("base64"),
2292
2280
  language: "ico",
2293
2281
  encoding: "base64"
2294
2282
  });
@@ -2302,12 +2290,12 @@ function generateServer(config) {
2302
2290
  }
2303
2291
 
2304
2292
  // ../../packages/core/src/generator/generate-agent-server.ts
2305
- function lang2(path14) {
2306
- if (path14.endsWith(".json")) return "json";
2307
- if (path14.endsWith(".mjs") || path14.endsWith(".js")) return "javascript";
2308
- if (path14.endsWith(".md")) return "markdown";
2309
- if (path14.endsWith("Dockerfile")) return "dockerfile";
2310
- if (path14.endsWith(".yml") || path14.endsWith(".yaml")) return "yaml";
2293
+ function lang2(path13) {
2294
+ if (path13.endsWith(".json")) return "json";
2295
+ if (path13.endsWith(".mjs") || path13.endsWith(".js")) return "javascript";
2296
+ if (path13.endsWith(".md")) return "markdown";
2297
+ if (path13.endsWith("Dockerfile")) return "dockerfile";
2298
+ if (path13.endsWith(".yml") || path13.endsWith(".yaml")) return "yaml";
2311
2299
  return "text";
2312
2300
  }
2313
2301
  function lancedbStore2() {
@@ -3321,22 +3309,22 @@ function generateAgentServer(config) {
3321
3309
  { path: "README.md", contents: readme2(config, server) }
3322
3310
  ].map((f) => ({ ...f, language: lang2(f.path) }));
3323
3311
  try {
3324
- const fs13 = __require("fs");
3325
- const path14 = __require("path");
3326
- const faviconPath = path14.resolve(process.cwd(), "public/favicon2.ico");
3327
- if (fs13.existsSync(faviconPath)) {
3312
+ const fs12 = __require("fs");
3313
+ const path13 = __require("path");
3314
+ const faviconPath = path13.resolve(process.cwd(), "public/favicon2.ico");
3315
+ if (fs12.existsSync(faviconPath)) {
3328
3316
  files.push({
3329
3317
  path: "public/favicon2.ico",
3330
- contents: fs13.readFileSync(faviconPath).toString("base64"),
3318
+ contents: fs12.readFileSync(faviconPath).toString("base64"),
3331
3319
  language: "ico",
3332
3320
  encoding: "base64"
3333
3321
  });
3334
3322
  } else {
3335
- const webFaviconPath = path14.resolve(process.cwd(), "apps/web/public/favicon2.ico");
3336
- if (fs13.existsSync(webFaviconPath)) {
3323
+ const webFaviconPath = path13.resolve(process.cwd(), "apps/web/public/favicon2.ico");
3324
+ if (fs12.existsSync(webFaviconPath)) {
3337
3325
  files.push({
3338
3326
  path: "public/favicon2.ico",
3339
- contents: fs13.readFileSync(webFaviconPath).toString("base64"),
3327
+ contents: fs12.readFileSync(webFaviconPath).toString("base64"),
3340
3328
  language: "ico",
3341
3329
  encoding: "base64"
3342
3330
  });
@@ -4313,7 +4301,7 @@ async function createAdapter(config, onRateLimit) {
4313
4301
  }
4314
4302
  case "lancedb":
4315
4303
  default: {
4316
- const { LanceDBAdapter } = await import("./lancedb-ITW7V3K5.js");
4304
+ const { LanceDBAdapter } = await import("./lancedb-RUTGJYW7.js");
4317
4305
  return new LanceDBAdapter({
4318
4306
  mode: overrides.mode,
4319
4307
  dbPath: overrides.dbPath,
@@ -4653,8 +4641,8 @@ async function readTextFiles(files) {
4653
4641
  }
4654
4642
 
4655
4643
  // src/commands/media.ts
4656
- import { promises as fs9 } from "fs";
4657
- import path10 from "path";
4644
+ import { promises as fs8 } from "fs";
4645
+ import path9 from "path";
4658
4646
 
4659
4647
  // ../../packages/core/src/media-store.ts
4660
4648
  import { promises as fs7 } from "fs";
@@ -4796,97 +4784,10 @@ function claimMediaAsset(id) {
4796
4784
  });
4797
4785
  }
4798
4786
 
4799
- // ../../packages/marketplace/src/storage-provider.ts
4800
- import { promises as fs8 } from "fs";
4801
- import path9 from "path";
4802
- var LocalStorageProvider = class {
4803
- id = "local";
4804
- name = "Local Storage";
4805
- async mediaDir() {
4806
- const dataDir = await requireDataDir();
4807
- const dir = path9.join(dataDir, "media");
4808
- await fs8.mkdir(dir, { recursive: true });
4809
- return dir;
4810
- }
4811
- async store(key, data, _mimeType) {
4812
- const dir = await this.mediaDir();
4813
- const filePath = path9.join(dir, key);
4814
- await fs8.mkdir(path9.dirname(filePath), { recursive: true });
4815
- await fs8.writeFile(filePath, data);
4816
- return `local://${key}`;
4817
- }
4818
- async storeFile(key, sourcePath, _mimeType) {
4819
- const dir = await this.mediaDir();
4820
- const filePath = path9.join(dir, key);
4821
- await fs8.mkdir(path9.dirname(filePath), { recursive: true });
4822
- await fs8.copyFile(sourcePath, filePath);
4823
- return `local://${key}`;
4824
- }
4825
- async retrieve(uri) {
4826
- const filePath = await this.resolvePath(uri);
4827
- if (!filePath) throw new Error(`Unsupported local storage URI: ${uri}`);
4828
- return fs8.readFile(filePath);
4829
- }
4830
- async resolvePath(uri) {
4831
- if (!uri.startsWith("local://")) return void 0;
4832
- const key = uri.slice("local://".length);
4833
- const dir = await this.mediaDir();
4834
- const filePath = path9.resolve(dir, key);
4835
- const relative = path9.relative(dir, filePath);
4836
- if (relative.startsWith("..") || path9.isAbsolute(relative)) {
4837
- throw new Error("Invalid local storage URI");
4838
- }
4839
- return filePath;
4840
- }
4841
- async delete(uri) {
4842
- const key = uri.replace("local://", "");
4843
- const dir = await this.mediaDir();
4844
- try {
4845
- await fs8.unlink(path9.join(dir, key));
4846
- } catch {
4847
- }
4848
- }
4849
- async stats() {
4850
- try {
4851
- const dir = await this.mediaDir();
4852
- return await computeDirStats(dir);
4853
- } catch {
4854
- return { usedBytes: 0, fileCount: 0 };
4855
- }
4856
- }
4857
- };
4858
- async function computeDirStats(dir) {
4859
- let usedBytes = 0;
4860
- let fileCount = 0;
4861
- async function walk2(d) {
4862
- let entries;
4863
- try {
4864
- entries = await fs8.readdir(d, { withFileTypes: true });
4865
- } catch {
4866
- return;
4867
- }
4868
- for (const entry of entries) {
4869
- const full = path9.join(d, entry.name);
4870
- if (entry.isDirectory()) {
4871
- await walk2(full);
4872
- } else {
4873
- try {
4874
- const stat = await fs8.stat(full);
4875
- usedBytes += stat.size;
4876
- fileCount++;
4877
- } catch {
4878
- }
4879
- }
4880
- }
4881
- }
4882
- await walk2(dir);
4883
- return { usedBytes, fileCount };
4884
- }
4885
- function createStorageProvider(_config) {
4886
- return new LocalStorageProvider();
4887
- }
4888
-
4889
4787
  // src/commands/media.ts
4788
+ import { isToolInstalled } from "@larkup/marketplace/installer";
4789
+ import { loadTool } from "@larkup/marketplace/loader";
4790
+ import { createStorageProvider } from "@larkup/marketplace/storage";
4890
4791
  var MIME_TYPES = {
4891
4792
  ".png": "image/png",
4892
4793
  ".jpg": "image/jpeg",
@@ -4928,12 +4829,12 @@ async function processMediaCommand(inputs, options) {
4928
4829
  const assets = await Promise.all(
4929
4830
  mediaFiles.map(async (filePath) => {
4930
4831
  const type = mediaType(filePath);
4931
- const stat = await fs9.stat(filePath);
4932
- const extension = path10.extname(filePath).toLowerCase() || ".bin";
4832
+ const stat = await fs8.stat(filePath);
4833
+ const extension = path9.extname(filePath).toLowerCase() || ".bin";
4933
4834
  const key = `${type}s/${Date.now()}_${Math.random().toString(36).slice(2)}${extension}`;
4934
4835
  const mimeType = MIME_TYPES[extension] || "application/octet-stream";
4935
- const storageUri = storage.storeFile ? await storage.storeFile(key, filePath, mimeType) : await storage.store(key, await fs9.readFile(filePath), mimeType);
4936
- return { type, fileName: path10.basename(filePath), mimeType, storageUri, fileSize: stat.size };
4836
+ const storageUri = storage.storeFile ? await storage.storeFile(key, filePath, mimeType) : await storage.store(key, await fs8.readFile(filePath), mimeType);
4837
+ return { type, fileName: path9.basename(filePath), mimeType, storageUri, fileSize: stat.size };
4937
4838
  })
4938
4839
  );
4939
4840
  const stored = await addMediaAssets(assets);
@@ -5015,7 +4916,7 @@ async function processMediaAsset(asset) {
5015
4916
  if (!tool2.processVideo)
5016
4917
  throw new Error("The installed Video & Audio tool cannot process videos.");
5017
4918
  await update("Extracting video audio", 20);
5018
- const outputDir = await fs9.mkdtemp(path10.join(process.cwd(), ".larkup", "tmp-media-"));
4919
+ const outputDir = await fs8.mkdtemp(path9.join(process.cwd(), ".larkup", "tmp-media-"));
5019
4920
  try {
5020
4921
  const video = await tool2.processVideo(localFile, {
5021
4922
  outputDir,
@@ -5036,7 +4937,7 @@ async function processMediaAsset(asset) {
5036
4937
  dimensions = { width: video.meta.width, height: video.meta.height };
5037
4938
  frameCount = video.frames.length;
5038
4939
  } finally {
5039
- await fs9.rm(outputDir, { recursive: true, force: true }).catch(() => {
4940
+ await fs8.rm(outputDir, { recursive: true, force: true }).catch(() => {
5040
4941
  });
5041
4942
  }
5042
4943
  } else {
@@ -5114,7 +5015,7 @@ async function indexPendingMedia() {
5114
5015
  spinner2.stop(`Indexed ${finalRun.totalChunks} chunks`);
5115
5016
  }
5116
5017
  function mediaType(filePath) {
5117
- const extension = path10.extname(filePath).toLowerCase();
5018
+ const extension = path9.extname(filePath).toLowerCase();
5118
5019
  if ([".png", ".jpg", ".jpeg", ".webp", ".gif"].includes(extension)) return "image";
5119
5020
  if ([".mp4", ".webm", ".mov", ".mkv"].includes(extension)) return "video";
5120
5021
  if ([".mp3", ".m4a", ".wav", ".ogg", ".flac"].includes(extension)) return "audio";
@@ -5201,20 +5102,20 @@ async function indexCommand(inputs, options) {
5201
5102
  }
5202
5103
 
5203
5104
  // src/commands/generate.ts
5204
- import { promises as fs10 } from "fs";
5205
- import path11 from "path";
5105
+ import { promises as fs9 } from "fs";
5106
+ import path10 from "path";
5206
5107
  async function generateCommand(options) {
5207
5108
  await inServerScope(options.server, async () => {
5208
5109
  await requireActive();
5209
5110
  const config = await readConfig();
5210
5111
  if (options.out) {
5211
- const dir = path11.isAbsolute(options.out) ? options.out : path11.join(process.cwd(), options.out);
5112
+ const dir = path10.isAbsolute(options.out) ? options.out : path10.join(process.cwd(), options.out);
5212
5113
  const server2 = generateServer(config);
5213
- await fs10.mkdir(dir, { recursive: true });
5114
+ await fs9.mkdir(dir, { recursive: true });
5214
5115
  for (const f of server2.files) {
5215
- const dest = path11.join(dir, f.path);
5216
- await fs10.mkdir(path11.dirname(dest), { recursive: true });
5217
- await fs10.writeFile(dest, f.contents, "utf8");
5116
+ const dest = path10.join(dir, f.path);
5117
+ await fs9.mkdir(path10.dirname(dest), { recursive: true });
5118
+ await fs9.writeFile(dest, f.contents, "utf8");
5218
5119
  }
5219
5120
  log.success(`Generated ${server2.files.length} files \u2192 ${dir}`);
5220
5121
  } else {
@@ -5519,6 +5420,13 @@ async function settingsCommand(options) {
5519
5420
  }
5520
5421
 
5521
5422
  // src/commands/marketplace.ts
5423
+ import { getAllTools, getToolById } from "@larkup/marketplace/registry";
5424
+ import {
5425
+ getInstalledTool,
5426
+ getInstalledTools,
5427
+ installTool,
5428
+ uninstallTool
5429
+ } from "@larkup/marketplace/installer";
5522
5430
  async function marketplaceCommand(action = "list", toolId) {
5523
5431
  if (action === "list") {
5524
5432
  const [tools, installed] = await Promise.all([getAllTools(), getInstalledTools()]);
@@ -5562,8 +5470,8 @@ async function marketplaceCommand(action = "list", toolId) {
5562
5470
  }
5563
5471
 
5564
5472
  // src/commands/deploy.ts
5565
- import { promises as fs11 } from "fs";
5566
- import path12 from "path";
5473
+ import { promises as fs10 } from "fs";
5474
+ import path11 from "path";
5567
5475
  async function deployCommand(target, options) {
5568
5476
  await inServerScope(options.server, async () => {
5569
5477
  await requireActive();
@@ -5599,13 +5507,13 @@ async function deployCommand(target, options) {
5599
5507
  });
5600
5508
  }
5601
5509
  async function copyGenerated(source, output) {
5602
- const destination = path12.resolve(output);
5603
- const relative = path12.relative(source, destination);
5604
- if (relative === "" || !relative.startsWith("..") && !path12.isAbsolute(relative)) {
5510
+ const destination = path11.resolve(output);
5511
+ const relative = path11.relative(source, destination);
5512
+ if (relative === "" || !relative.startsWith("..") && !path11.isAbsolute(relative)) {
5605
5513
  throw new Error("Deployment output must be outside the generated server directory.");
5606
5514
  }
5607
- await fs11.mkdir(destination, { recursive: true });
5608
- await fs11.cp(source, destination, { recursive: true, force: true });
5515
+ await fs10.mkdir(destination, { recursive: true });
5516
+ await fs10.cp(source, destination, { recursive: true, force: true });
5609
5517
  return destination;
5610
5518
  }
5611
5519
 
@@ -5690,8 +5598,8 @@ function openCommandForPlatform(url) {
5690
5598
  }
5691
5599
 
5692
5600
  // src/commands/documents.ts
5693
- import { promises as fs12 } from "fs";
5694
- import path13 from "path";
5601
+ import { promises as fs11 } from "fs";
5602
+ import path12 from "path";
5695
5603
 
5696
5604
  // ../../packages/core/src/corpus-retriever.ts
5697
5605
  function applyFilters(docs, filter) {
@@ -5810,10 +5718,10 @@ async function documentsCommand(action = "list", idOrPath, options) {
5810
5718
  }
5811
5719
  if (action === "export") {
5812
5720
  const format = options.format === "jsonl" ? "jsonl" : "csv";
5813
- const output = path13.resolve(options.out || idOrPath || `corpus.${format}`);
5721
+ const output = path12.resolve(options.out || idOrPath || `corpus.${format}`);
5814
5722
  const content = format === "jsonl" ? await exportCorpusAsJSONL(void 0, Number.MAX_SAFE_INTEGER) : await exportCorpusAsCSV(void 0, Number.MAX_SAFE_INTEGER);
5815
- await fs12.mkdir(path13.dirname(output), { recursive: true });
5816
- await fs12.writeFile(output, content, "utf8");
5723
+ await fs11.mkdir(path12.dirname(output), { recursive: true });
5724
+ await fs11.writeFile(output, content, "utf8");
5817
5725
  log.success(`Exported corpus \u2192 ${output}`);
5818
5726
  return;
5819
5727
  }
@@ -5839,7 +5747,7 @@ ${document.content}`);
5839
5747
  return;
5840
5748
  }
5841
5749
  if (action === "update") {
5842
- const content = options.file ? await fs12.readFile(path13.resolve(options.file), "utf8") : options.text;
5750
+ const content = options.file ? await fs11.readFile(path12.resolve(options.file), "utf8") : options.text;
5843
5751
  const updated = await updateDocument(document.id, {
5844
5752
  title: options.title,
5845
5753
  content,
@@ -112,7 +112,7 @@ var LanceDBAdapter = class {
112
112
  source: r.source,
113
113
  documentId: r.documentId,
114
114
  chunkIndex: r.chunkIndex,
115
- metadata: r.metadata ? JSON.stringify(r.metadata) : void 0
115
+ metadata: JSON.stringify(r.metadata ?? {})
116
116
  };
117
117
  }
118
118
  async upsert(records) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@larkup/cli",
3
- "version": "0.2.6",
3
+ "version": "0.2.7",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -28,9 +28,9 @@
28
28
  "cli-table3": "^0.6.5",
29
29
  "commander": "^15.0.0",
30
30
  "zod": "^4.4.3",
31
- "@larkup/marketplace": "0.1.6",
32
- "@larkup/vector-stores": "0.1.22",
33
- "@larkup/core": "0.2.3"
31
+ "@larkup/core": "0.2.4",
32
+ "@larkup/marketplace": "0.1.7",
33
+ "@larkup/vector-stores": "0.1.23"
34
34
  },
35
35
  "devDependencies": {
36
36
  "tsup": "^8.0.0",
@@ -1,231 +0,0 @@
1
- // ../../packages/marketplace/src/tool-registry.ts
2
- import { promises as fs } from "fs";
3
- import path from "path";
4
-
5
- // ../../packages/marketplace/src/types.ts
6
- var DEFAULT_HUB_URL = process.env.LARKUP_HUB_URL ?? "https://hub.larkup.de";
7
- var STORAGE_WARNING_THRESHOLDS = [
8
- 1 * 1024 * 1024 * 1024,
9
- // 1 GB
10
- 5 * 1024 * 1024 * 1024,
11
- // 5 GB
12
- 10 * 1024 * 1024 * 1024
13
- // 10 GB
14
- ];
15
-
16
- // ../../packages/marketplace/src/tool-registry.ts
17
- var cachedRegistry = null;
18
- async function discoverLocalManifests() {
19
- const registry = {};
20
- const searchPaths = [
21
- // Monorepo development: packages/tools/*
22
- path.resolve(process.cwd(), "packages", "tools"),
23
- // Next.js dev server runs in apps/web
24
- path.resolve(process.cwd(), "..", "..", "packages", "tools"),
25
- // Installed tools: .larkup/tools/node_modules/@larkup
26
- path.resolve(process.cwd(), ".larkup", "tools", "node_modules", "@larkup"),
27
- path.resolve(process.cwd(), "..", "..", ".larkup", "tools", "node_modules", "@larkup")
28
- ];
29
- for (const searchPath of searchPaths) {
30
- try {
31
- const entries = await fs.readdir(searchPath, { withFileTypes: true });
32
- for (const entry of entries) {
33
- if (!entry.isDirectory()) continue;
34
- const manifestPath = path.join(searchPath, entry.name, "tool.manifest.json");
35
- try {
36
- const raw = await fs.readFile(manifestPath, "utf8");
37
- const manifest = JSON.parse(raw);
38
- if (manifest.id) {
39
- registry[manifest.id] = manifest;
40
- }
41
- } catch {
42
- }
43
- }
44
- } catch {
45
- }
46
- }
47
- return registry;
48
- }
49
- async function fetchHubCatalog(hubUrl) {
50
- const baseUrl = hubUrl ?? DEFAULT_HUB_URL;
51
- try {
52
- const controller = new AbortController();
53
- const timeout = setTimeout(() => controller.abort(), 5e3);
54
- const res = await fetch(`${baseUrl}/v1/tools`, {
55
- signal: controller.signal,
56
- headers: { Accept: "application/json" }
57
- });
58
- clearTimeout(timeout);
59
- if (!res.ok) return {};
60
- const data = await res.json();
61
- const registry = {};
62
- for (const tool of data.tools ?? []) {
63
- if (tool.id) registry[tool.id] = tool;
64
- }
65
- return registry;
66
- } catch {
67
- return {};
68
- }
69
- }
70
- async function fetchToolFromHub(toolId, hubUrl) {
71
- const baseUrl = hubUrl ?? DEFAULT_HUB_URL;
72
- try {
73
- const controller = new AbortController();
74
- const timeout = setTimeout(() => controller.abort(), 5e3);
75
- const res = await fetch(`${baseUrl}/v1/tools/${toolId}`, {
76
- signal: controller.signal,
77
- headers: { Accept: "application/json" }
78
- });
79
- clearTimeout(timeout);
80
- if (!res.ok) return null;
81
- const data = await res.json();
82
- return data.tool ?? null;
83
- } catch {
84
- return null;
85
- }
86
- }
87
- var FALLBACK_REGISTRY = {
88
- "video-audio": {
89
- id: "video-audio",
90
- name: "Video & Audio",
91
- description: "Index video and audio files with transcription and frame analysis.",
92
- category: "media",
93
- version: "0.2.1",
94
- pricing: "free",
95
- emoji: "\u{1F3AC}",
96
- icon: "Film",
97
- packageName: "@larkup/tool-video-audio",
98
- installSize: "~15 MB",
99
- systemDeps: ["ffmpeg"],
100
- author: "Larkup",
101
- capabilities: [
102
- "video-indexing",
103
- "audio-indexing",
104
- "transcription",
105
- "frame-extraction",
106
- "youtube-import"
107
- ],
108
- tags: ["transcription", "ffmpeg", "video", "audio", "whisper"],
109
- downloads: 0,
110
- repositoryUrl: "https://github.com/Larkup-AI/larkup-rag",
111
- license: "Apache-2.0",
112
- updatedAt: "2026-07-20",
113
- configSchema: [
114
- {
115
- key: "frameInterval",
116
- label: "Frame extraction interval (seconds)",
117
- type: "text",
118
- defaultValue: "10",
119
- help: "Baseline cadence for duration-aware coverage frames; scene changes and a reserved ending pass are added separately."
120
- },
121
- {
122
- key: "audioProvider",
123
- label: "Audio Provider",
124
- type: "select",
125
- help: "Choose the provider used only for audio and video transcription.",
126
- options: [
127
- { label: "OpenAI", value: "openai" },
128
- { label: "Groq", value: "groq" },
129
- { label: "Deepgram", value: "deepgram" },
130
- { label: "ElevenLabs", value: "elevenlabs" },
131
- { label: "Local Whisper", value: "local" }
132
- ]
133
- },
134
- {
135
- key: "audioLanguage",
136
- label: "Transcription language",
137
- type: "text",
138
- defaultValue: "auto",
139
- help: "Use auto to infer Arabic from the media title and use provider detection otherwise. Enter a language code such as ar, ar-EG, en, or de to override it."
140
- },
141
- {
142
- key: "audioApiKey",
143
- label: "Audio API Key",
144
- type: "password",
145
- help: "Required for the selected audio provider and kept separate from the chat model key."
146
- }
147
- ]
148
- },
149
- "clip-embeddings": {
150
- id: "clip-embeddings",
151
- name: "CLIP Image Search",
152
- description: "Direct image-to-image similarity search using CLIP/SigLIP embeddings.",
153
- category: "embedding",
154
- version: "0.1.0",
155
- pricing: "free",
156
- emoji: "\u{1F50D}",
157
- icon: "ScanEye",
158
- packageName: "@larkup/tool-clip-embeddings",
159
- installSize: "~200 MB",
160
- author: "Larkup",
161
- capabilities: ["clip-embeddings", "image-similarity"],
162
- tags: ["clip", "siglip", "image-search", "visual-similarity"],
163
- downloads: 0,
164
- repositoryUrl: "https://github.com/Larkup-AI/larkup-rag",
165
- license: "Apache-2.0",
166
- updatedAt: "2026-07-20",
167
- comingSoon: true
168
- },
169
- "doc-editor": {
170
- id: "doc-editor",
171
- name: "Document Editor",
172
- description: "AI-powered form filling and document editing with Canvas-style live preview.",
173
- category: "utility",
174
- version: "0.2.3",
175
- pricing: "free",
176
- emoji: "\u{1F4DD}",
177
- icon: "FileEdit",
178
- packageName: "@larkup/tool-doc-editor",
179
- installSize: "~5 MB",
180
- systemDeps: ["docker"],
181
- author: "Larkup",
182
- capabilities: ["document-editing", "form-filling", "document-preview"],
183
- tags: ["pdf", "docx", "pptx", "form", "canvas", "editor", "fill"],
184
- downloads: 0,
185
- repositoryUrl: "https://github.com/Larkup-AI/larkup-rag",
186
- license: "Apache-2.0",
187
- updatedAt: "2026-07-20"
188
- }
189
- };
190
- async function buildRegistry(opts) {
191
- if (cachedRegistry) return cachedRegistry;
192
- const registry = { ...FALLBACK_REGISTRY };
193
- const localManifests = await discoverLocalManifests();
194
- Object.assign(registry, localManifests);
195
- if (!opts?.skipHub) {
196
- const hubCatalog = await fetchHubCatalog(opts?.hubUrl);
197
- Object.assign(registry, hubCatalog);
198
- }
199
- cachedRegistry = registry;
200
- return registry;
201
- }
202
- function invalidateRegistryCache() {
203
- cachedRegistry = null;
204
- }
205
- async function getAllTools() {
206
- const registry = await buildRegistry();
207
- return Object.values(registry).sort((a, b) => a.name.localeCompare(b.name));
208
- }
209
- async function getToolById(id) {
210
- const registry = await buildRegistry();
211
- return registry[id];
212
- }
213
- async function getToolsWithCapability(capability) {
214
- const all = await getAllTools();
215
- return all.filter((t) => t.capabilities.includes(capability));
216
- }
217
- async function getAllCategories() {
218
- const all = await getAllTools();
219
- const cats = new Set(all.map((t) => t.category));
220
- return Array.from(cats).sort();
221
- }
222
-
223
- export {
224
- fetchToolFromHub,
225
- buildRegistry,
226
- invalidateRegistryCache,
227
- getAllTools,
228
- getToolById,
229
- getToolsWithCapability,
230
- getAllCategories
231
- };
@@ -1,424 +0,0 @@
1
- import {
2
- getToolById,
3
- invalidateRegistryCache
4
- } from "./chunk-P5JVXA7X.js";
5
- import {
6
- __require
7
- } from "./chunk-3RG5ZIWI.js";
8
-
9
- // ../../packages/marketplace/src/tool-loader.ts
10
- import { promises as fs2 } from "fs";
11
- import path2 from "path";
12
- import { pathToFileURL } from "url";
13
-
14
- // ../../packages/marketplace/src/tool-installer.ts
15
- import { promises as fs } from "fs";
16
- import path from "path";
17
- import { exec as execCb } from "child_process";
18
- import { promisify } from "util";
19
- var execAsync = promisify(execCb);
20
- function getToolsDir() {
21
- return path.join(process.cwd(), ".larkup", "tools");
22
- }
23
- function getManifestPath() {
24
- return path.join(getToolsDir(), "installed.json");
25
- }
26
- async function ensureDir() {
27
- await fs.mkdir(getToolsDir(), { recursive: true });
28
- }
29
- async function readManifest() {
30
- try {
31
- const raw = await fs.readFile(getManifestPath(), "utf8");
32
- const parsed = JSON.parse(raw);
33
- if (!parsed.downloadCounts) parsed.downloadCounts = {};
34
- for (const tool of parsed.tools ?? []) {
35
- if (tool.packagePath && !tool.packageName) {
36
- tool.packageName = tool.packagePath;
37
- delete tool.packagePath;
38
- }
39
- if (!tool.source) tool.source = "local";
40
- if (!tool.resolvedPath) {
41
- tool.resolvedPath = tool.packageName;
42
- }
43
- }
44
- return parsed;
45
- } catch {
46
- return { tools: [], downloadCounts: {}, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
47
- }
48
- }
49
- async function writeManifest(manifest) {
50
- await ensureDir();
51
- manifest.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
52
- await fs.writeFile(getManifestPath(), JSON.stringify(manifest, null, 2), "utf8");
53
- }
54
- async function getInstalledTools() {
55
- const manifest = await readManifest();
56
- const tools = [...manifest.tools];
57
- const bundledIds = (process.env.LARKUP_BUNDLED_TOOLS ?? "").split(",").map((id) => id.trim()).filter(Boolean);
58
- for (const toolId of bundledIds) {
59
- if (tools.some((tool) => tool.id === toolId)) continue;
60
- const descriptor = await getToolById(toolId);
61
- if (!descriptor) continue;
62
- tools.push({
63
- id: toolId,
64
- version: descriptor.version,
65
- installedAt: "bundled",
66
- packageName: descriptor.packageName,
67
- resolvedPath: descriptor.packageName,
68
- source: "local",
69
- config: buildDefaultConfig(descriptor)
70
- });
71
- }
72
- return tools;
73
- }
74
- async function isToolInstalled(toolId) {
75
- const tools = await getInstalledTools();
76
- return tools.some((t) => t.id === toolId);
77
- }
78
- async function getInstalledTool(toolId) {
79
- const tools = await getInstalledTools();
80
- return tools.find((t) => t.id === toolId);
81
- }
82
- async function checkSystemDeps(toolId) {
83
- const descriptor = await getToolById(toolId);
84
- if (!descriptor?.systemDeps?.length) return [];
85
- const target = detectDeploymentTarget();
86
- const missing = [];
87
- for (const dep of descriptor.systemDeps) {
88
- if (target === "docker" && dep === "docker") continue;
89
- try {
90
- await execAsync(`which ${dep}`);
91
- } catch {
92
- missing.push(dep);
93
- }
94
- }
95
- return missing;
96
- }
97
- function detectDeploymentTarget() {
98
- const explicit = process.env.LARKUP_DEPLOYMENT_TARGET;
99
- if (explicit && ["local", "docker", "serverless", "sandbox"].includes(explicit)) {
100
- return explicit;
101
- }
102
- if (process.env.VERCEL || process.env.AWS_LAMBDA_FUNCTION_NAME) return "serverless";
103
- if (process.env.DOCKER_CONTAINER || isDockerEnvironment()) return "docker";
104
- if (process.env.E2B_SANDBOX_ID || process.env.MODAL_TASK_ID) return "sandbox";
105
- return "local";
106
- }
107
- function isDockerEnvironment() {
108
- try {
109
- const fs3 = __require("fs");
110
- return fs3.existsSync("/.dockerenv");
111
- } catch {
112
- return false;
113
- }
114
- }
115
- async function ensureToolsPackageJson() {
116
- const toolsDir = getToolsDir();
117
- const pkgPath = path.join(toolsDir, "package.json");
118
- try {
119
- await fs.access(pkgPath);
120
- } catch {
121
- await ensureDir();
122
- await fs.writeFile(
123
- pkgPath,
124
- JSON.stringify(
125
- {
126
- name: "larkup-tools",
127
- version: "1.0.0",
128
- private: true,
129
- description: "Isolated directory for installed Larkup marketplace tools."
130
- },
131
- null,
132
- 2
133
- ),
134
- "utf8"
135
- );
136
- }
137
- }
138
- async function execInstall(packageName, version, target, onProgress) {
139
- const toolsDir = getToolsDir();
140
- switch (target) {
141
- case "local":
142
- case "docker": {
143
- await ensureToolsPackageJson();
144
- const install = async (specifier) => {
145
- const installCmd = `npm install ${specifier} --prefix "${toolsDir}" --save --no-audit --no-fund`;
146
- onProgress?.(`Running: npm install ${specifier}`);
147
- const { stderr } = await execAsync(installCmd, {
148
- cwd: toolsDir,
149
- // Native tool dependencies can take longer under Docker Desktop's
150
- // amd64 emulation. Let the request finish instead of reporting a
151
- // misleading connection error part way through installation.
152
- timeout: target === "docker" ? 3e5 : 12e4,
153
- env: {
154
- ...process.env,
155
- NODE_ENV: "production",
156
- // The Docker image runs as an unprivileged user. Keep npm's cache
157
- // beside the isolated install so a named .larkup volume is always
158
- // writable and installing a Marketplace tool does not fail before
159
- // it reaches the registry.
160
- HOME: process.env.HOME && process.env.HOME !== "/nonexistent" ? process.env.HOME : toolsDir,
161
- npm_config_cache: path.join(toolsDir, ".npm-cache"),
162
- npm_config_update_notifier: "false"
163
- }
164
- });
165
- if (stderr && !stderr.includes("npm warn")) {
166
- console.warn(`[marketplace] Install stderr: ${stderr}`);
167
- }
168
- };
169
- try {
170
- await install(`${packageName}@${version}`);
171
- } catch (err) {
172
- const message = err instanceof Error ? err.message : "Install command failed";
173
- if (!message.includes("ETARGET") && !message.includes("No matching version found")) {
174
- throw new Error(`Failed to install ${packageName}: ${message}`);
175
- }
176
- onProgress?.(
177
- `Catalog version ${version} is unavailable; installing the latest published version\u2026`
178
- );
179
- try {
180
- await install(`${packageName}@latest`);
181
- } catch (latestErr) {
182
- const latestMessage = latestErr instanceof Error ? latestErr.message : "Install command failed";
183
- throw new Error(`Failed to install ${packageName}: ${latestMessage}`);
184
- }
185
- }
186
- const resolvedPath = path.join(toolsDir, "node_modules", packageName);
187
- try {
188
- await fs.access(resolvedPath);
189
- } catch {
190
- throw new Error(
191
- `Package ${packageName} was installed but could not be found at ${resolvedPath}`
192
- );
193
- }
194
- const packageJson = JSON.parse(
195
- await fs.readFile(path.join(resolvedPath, "package.json"), "utf8")
196
- );
197
- return { resolvedPath, version: packageJson.version ?? version };
198
- }
199
- case "serverless": {
200
- onProgress?.("Serverless environment detected \u2014 queuing for next deploy");
201
- const pendingPath = path.join(toolsDir, "pending-tools.json");
202
- let pending = { tools: [] };
203
- try {
204
- const raw = await fs.readFile(pendingPath, "utf8");
205
- pending = JSON.parse(raw);
206
- } catch {
207
- }
208
- pending.tools.push({ packageName, version });
209
- await ensureDir();
210
- await fs.writeFile(pendingPath, JSON.stringify(pending, null, 2), "utf8");
211
- return { resolvedPath: path.join(toolsDir, "node_modules", packageName), version };
212
- }
213
- case "sandbox": {
214
- onProgress?.("Installing in sandbox environment");
215
- await ensureToolsPackageJson();
216
- const installCmd = `npm install ${packageName}@${version} --prefix "${toolsDir}" --save --no-audit --no-fund`;
217
- await execAsync(installCmd, { cwd: toolsDir, timeout: 12e4 });
218
- return { resolvedPath: path.join(toolsDir, "node_modules", packageName), version };
219
- }
220
- default:
221
- throw new Error(`Unsupported deployment target: ${target}`);
222
- }
223
- }
224
- async function resolveManifest(toolId) {
225
- const descriptor = await getToolById(toolId);
226
- if (descriptor) return descriptor;
227
- throw new Error(`Unknown tool: ${toolId}. Not found in local registry or Hub.`);
228
- }
229
- async function isWorkspaceTool(packageName) {
230
- try {
231
- const { stdout } = await execAsync(`pnpm ls -r --depth -1 --json 2>/dev/null || true`, {
232
- cwd: process.cwd(),
233
- timeout: 1e4
234
- });
235
- const data = JSON.parse(stdout || "[]");
236
- return Array.isArray(data) && data.some((pkg) => pkg.name === packageName);
237
- } catch {
238
- return false;
239
- }
240
- }
241
- async function installTool(toolId, onProgress) {
242
- const report = (stage, percent, message) => {
243
- onProgress?.({ toolId, stage, percent, message });
244
- };
245
- try {
246
- report("checking-deps", 5, "Resolving tool manifest\u2026");
247
- const descriptor = await resolveManifest(toolId);
248
- if (descriptor.comingSoon) {
249
- throw new Error(`${descriptor.name} is coming soon.`);
250
- }
251
- report("checking-deps", 15, "Checking system dependencies\u2026");
252
- const missing = await checkSystemDeps(toolId);
253
- if (missing.length > 0) {
254
- const msg = `Missing system dependencies: ${missing.join(", ")}. Please install them first.`;
255
- report("failed", 0, msg);
256
- throw new Error(msg);
257
- }
258
- const isWorkspace = await isWorkspaceTool(descriptor.packageName);
259
- const target = detectDeploymentTarget();
260
- let resolvedPath;
261
- let installedVersion = descriptor.version;
262
- let source;
263
- if (isWorkspace) {
264
- report("downloading", 30, "Resolving workspace package\u2026");
265
- try {
266
- const modulePath = __require.resolve(descriptor.packageName, {
267
- paths: [process.cwd()]
268
- });
269
- resolvedPath = path.dirname(modulePath);
270
- } catch {
271
- resolvedPath = path.join(process.cwd(), "node_modules", descriptor.packageName);
272
- }
273
- source = "local";
274
- report("installing", 60, "Workspace package resolved.");
275
- } else {
276
- report("downloading", 30, `Downloading ${descriptor.packageName}@${descriptor.version}\u2026`);
277
- const installed = await execInstall(
278
- descriptor.packageName,
279
- descriptor.version,
280
- target,
281
- (msg) => report("downloading", 50, msg)
282
- );
283
- resolvedPath = installed.resolvedPath;
284
- installedVersion = installed.version;
285
- source = target === "sandbox" ? "sandbox" : "registry";
286
- report("installing", 70, "Package installed.");
287
- }
288
- report("installing", 80, "Registering tool\u2026");
289
- await ensureDir();
290
- const manifest = await readManifest();
291
- const existing = manifest.tools.findIndex((t) => t.id === toolId);
292
- const entry = {
293
- id: toolId,
294
- version: installedVersion,
295
- installedAt: (/* @__PURE__ */ new Date()).toISOString(),
296
- packageName: descriptor.packageName,
297
- resolvedPath,
298
- source,
299
- config: buildDefaultConfig(descriptor)
300
- };
301
- if (existing >= 0) {
302
- manifest.tools[existing] = entry;
303
- } else {
304
- manifest.tools.push(entry);
305
- }
306
- manifest.downloadCounts[toolId] = (manifest.downloadCounts[toolId] ?? 0) + 1;
307
- await writeManifest(manifest);
308
- notifyHubInstall(toolId).catch(() => {
309
- });
310
- invalidateRegistryCache();
311
- report("completed", 100, "Installed successfully.");
312
- } catch (err) {
313
- const message = err instanceof Error ? err.message : "Installation failed.";
314
- report("failed", 0, message);
315
- throw err;
316
- }
317
- }
318
- async function uninstallTool(toolId) {
319
- const manifest = await readManifest();
320
- const tool = manifest.tools.find((t) => t.id === toolId);
321
- manifest.tools = manifest.tools.filter((t) => t.id !== toolId);
322
- await writeManifest(manifest);
323
- if (tool?.source === "registry" && tool.packageName) {
324
- try {
325
- const toolsDir = getToolsDir();
326
- await execAsync(`npm uninstall ${tool.packageName} --prefix "${toolsDir}"`, {
327
- cwd: toolsDir,
328
- timeout: 3e4
329
- });
330
- } catch {
331
- }
332
- }
333
- invalidateRegistryCache();
334
- const { unloadTool: unloadTool2 } = await import("./tool-loader-QU6HBUCA.js");
335
- unloadTool2(toolId);
336
- }
337
- async function notifyHubInstall(toolId) {
338
- const hubUrl = process.env.LARKUP_HUB_URL ?? "https://hub.larkup.de";
339
- try {
340
- const controller = new AbortController();
341
- const timeout = setTimeout(() => controller.abort(), 3e3);
342
- await fetch(`${hubUrl}/v1/tools/${toolId}/installed`, {
343
- method: "POST",
344
- signal: controller.signal,
345
- headers: { "Content-Type": "application/json" }
346
- });
347
- clearTimeout(timeout);
348
- } catch {
349
- }
350
- }
351
- function buildDefaultConfig(descriptor) {
352
- const config = {};
353
- for (const field of descriptor.configSchema ?? []) {
354
- if (field.defaultValue !== void 0) {
355
- config[field.key] = field.defaultValue;
356
- }
357
- }
358
- return config;
359
- }
360
-
361
- // ../../packages/marketplace/src/tool-loader.ts
362
- var moduleCache = /* @__PURE__ */ new Map();
363
- async function loadTool(toolId) {
364
- if (moduleCache.has(toolId)) return moduleCache.get(toolId);
365
- const installed = await getInstalledTool(toolId);
366
- if (!installed) return null;
367
- try {
368
- const importPath = await resolveImportPath(installed);
369
- const mod = await import(
370
- /* webpackIgnore: true */
371
- importPath
372
- );
373
- moduleCache.set(toolId, mod);
374
- return mod;
375
- } catch (err) {
376
- console.error(`[marketplace] Failed to load tool "${toolId}":`, err);
377
- return null;
378
- }
379
- }
380
- async function resolveImportPath(installed) {
381
- switch (installed.source) {
382
- case "local":
383
- return installed.packageName;
384
- case "registry":
385
- case "sandbox":
386
- return resolvePackageEntry(installed.resolvedPath);
387
- default:
388
- return installed.packageName;
389
- }
390
- }
391
- async function resolvePackageEntry(packageDir) {
392
- const manifestPath = path2.join(packageDir, "package.json");
393
- const manifest = JSON.parse(await fs2.readFile(manifestPath, "utf8"));
394
- const rootExport = typeof manifest.exports === "object" ? manifest.exports["."] : manifest.exports;
395
- const entry = (typeof rootExport === "object" ? rootExport.import ?? rootExport.default : rootExport) ?? manifest.main ?? "index.js";
396
- return pathToFileURL(path2.resolve(packageDir, entry)).href;
397
- }
398
- function isToolLoaded(toolId) {
399
- return moduleCache.has(toolId);
400
- }
401
- function unloadTool(toolId) {
402
- moduleCache.delete(toolId);
403
- }
404
- async function hasCapability(capability) {
405
- const { getToolsWithCapability } = await import("./tool-registry-W3JOGDE3.js");
406
- const tools = await getToolsWithCapability(capability);
407
- for (const t of tools) {
408
- const installed = await getInstalledTool(t.id);
409
- if (installed) return true;
410
- }
411
- return false;
412
- }
413
-
414
- export {
415
- loadTool,
416
- isToolLoaded,
417
- unloadTool,
418
- hasCapability,
419
- getInstalledTools,
420
- isToolInstalled,
421
- getInstalledTool,
422
- installTool,
423
- uninstallTool
424
- };
@@ -1,14 +0,0 @@
1
- import {
2
- hasCapability,
3
- isToolLoaded,
4
- loadTool,
5
- unloadTool
6
- } from "./chunk-VY6I42DP.js";
7
- import "./chunk-P5JVXA7X.js";
8
- import "./chunk-3RG5ZIWI.js";
9
- export {
10
- hasCapability,
11
- isToolLoaded,
12
- loadTool,
13
- unloadTool
14
- };
@@ -1,19 +0,0 @@
1
- import {
2
- buildRegistry,
3
- fetchToolFromHub,
4
- getAllCategories,
5
- getAllTools,
6
- getToolById,
7
- getToolsWithCapability,
8
- invalidateRegistryCache
9
- } from "./chunk-P5JVXA7X.js";
10
- import "./chunk-3RG5ZIWI.js";
11
- export {
12
- buildRegistry,
13
- fetchToolFromHub,
14
- getAllCategories,
15
- getAllTools,
16
- getToolById,
17
- getToolsWithCapability,
18
- invalidateRegistryCache
19
- };