@looplia/looplia-cli 0.7.0 → 0.7.1

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.
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env bun
2
+ import {
3
+ init_esm_shims
4
+ } from "./chunk-Y55L47HC.js";
5
+
6
+ // src/utils/sandbox.ts
7
+ init_esm_shims();
8
+ import { randomBytes } from "crypto";
9
+ import { mkdirSync } from "fs";
10
+ import { join } from "path";
11
+ var SANDBOX_DIRS = {
12
+ INPUTS: "inputs",
13
+ OUTPUTS: "outputs",
14
+ LOGS: "logs"
15
+ };
16
+ function generateRandomSuffix() {
17
+ return randomBytes(2).toString("hex");
18
+ }
19
+ function generateSlug(input, maxLength = 30) {
20
+ return input.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").substring(0, maxLength);
21
+ }
22
+ function generateSandboxId(slug) {
23
+ const normalizedSlug = generateSlug(slug);
24
+ const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
25
+ const suffix = generateRandomSuffix();
26
+ return `${normalizedSlug}-${date}-${suffix}`;
27
+ }
28
+ function createSandboxDirectories(workspace, sandboxId) {
29
+ const sandboxDir = join(workspace, "sandbox", sandboxId);
30
+ mkdirSync(join(sandboxDir, SANDBOX_DIRS.INPUTS), { recursive: true });
31
+ mkdirSync(join(sandboxDir, SANDBOX_DIRS.OUTPUTS), { recursive: true });
32
+ mkdirSync(join(sandboxDir, SANDBOX_DIRS.LOGS), { recursive: true });
33
+ return sandboxDir;
34
+ }
35
+
36
+ export {
37
+ SANDBOX_DIRS,
38
+ generateRandomSuffix,
39
+ generateSlug,
40
+ generateSandboxId,
41
+ createSandboxDirectories
42
+ };
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bun
2
+ import {
3
+ init_esm_shims
4
+ } from "./chunk-Y55L47HC.js";
5
+
6
+ // ../../packages/provider/dist/claude-agent-sdk/index.js
7
+ init_esm_shims();
@@ -1,9 +1,13 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env bun
2
2
  import {
3
3
  pathExists
4
- } from "./chunk-FCL2HRTX.js";
4
+ } from "./chunk-VRBGWKZ6.js";
5
+ import {
6
+ init_esm_shims
7
+ } from "./chunk-Y55L47HC.js";
5
8
 
6
- // ../../packages/provider/dist/chunk-NOF2J4UK.js
9
+ // ../../packages/provider/dist/chunk-M7EZUTK7.js
10
+ init_esm_shims();
7
11
  import { exec } from "child_process";
8
12
  import { mkdir, readdir, readFile, writeFile } from "fs/promises";
9
13
  import { homedir } from "os";
@@ -26,6 +30,14 @@ function createProgress() {
26
30
  console.log(`\u2713 ${message ?? currentMessage}`);
27
31
  isActive = false;
28
32
  },
33
+ warn(message) {
34
+ if (!isActive) {
35
+ return;
36
+ }
37
+ process.stdout.write("\r\x1B[K");
38
+ console.log(`\u26A0 ${message ?? currentMessage}`);
39
+ isActive = false;
40
+ },
29
41
  fail(message) {
30
42
  if (!isActive) {
31
43
  return;
@@ -50,14 +62,6 @@ function createProgress() {
50
62
  }
51
63
  };
52
64
  }
53
- var execAsync = promisify(exec);
54
- var OFFICIAL_REGISTRY_URL = "https://github.com/memorysaver/looplia-core/releases/latest/download/registry.json";
55
- var REGISTRY_SCHEMA_URL = "https://looplia.com/schema/registry.json";
56
- var REGISTRY_VERSION = "1.0.0";
57
- var PROTOCOL_REGEX = /^https?:\/\//;
58
- var TRAILING_SLASH_REGEX = /\/$/;
59
- var LEADING_DOT_SLASH_REGEX = /^\.\//;
60
- var FRONTMATTER_REGEX = /^---\n([\s\S]*?)\n---/;
61
65
  var CAPABILITY_PATTERNS = [
62
66
  { pattern: /media|video|audio|image/, capability: "media-processing" },
63
67
  { pattern: /content|text|document/, capability: "content-analysis" },
@@ -67,6 +71,100 @@ var CAPABILITY_PATTERNS = [
67
71
  { pattern: /generat|creat|produc/, capability: "generation" },
68
72
  { pattern: /valid|check|verify/, capability: "validation" }
69
73
  ];
74
+ var FRONTMATTER_REGEX = /^---\n([\s\S]*?)\n---/;
75
+ var PROTOCOL_REGEX = /^https?:\/\//;
76
+ var TRAILING_SLASH_REGEX = /\/$/;
77
+ var LEADING_DOT_SLASH_REGEX = /^\.\//;
78
+ function parseMultilineValue(lines, startIndex) {
79
+ const multilineLines = [];
80
+ for (let j = startIndex; j < lines.length; j++) {
81
+ const nextLine = lines[j];
82
+ if (nextLine === void 0) {
83
+ break;
84
+ }
85
+ if (nextLine.startsWith(" ")) {
86
+ multilineLines.push(nextLine.trim());
87
+ } else if (nextLine.trim() !== "") {
88
+ break;
89
+ }
90
+ }
91
+ return multilineLines.join(" ");
92
+ }
93
+ function parseYamlFrontmatter(frontmatter) {
94
+ const lines = frontmatter.split("\n");
95
+ const metadata = {};
96
+ for (let i = 0; i < lines.length; i++) {
97
+ const line = lines[i];
98
+ if (line === void 0) {
99
+ continue;
100
+ }
101
+ const colonIndex = line.indexOf(":");
102
+ if (colonIndex <= 0) {
103
+ continue;
104
+ }
105
+ const key = line.slice(0, colonIndex).trim();
106
+ let value = line.slice(colonIndex + 1).trim();
107
+ if (value === "|") {
108
+ value = parseMultilineValue(lines, i + 1);
109
+ }
110
+ metadata[key] = value;
111
+ }
112
+ return metadata;
113
+ }
114
+ function inferCategory(name, description) {
115
+ const text = `${name} ${description}`.toLowerCase();
116
+ if (text.includes("review") || text.includes("analyze") || text.includes("scan")) {
117
+ return "analysis";
118
+ }
119
+ if (text.includes("generate") || text.includes("synthesis") || text.includes("create")) {
120
+ return "generation";
121
+ }
122
+ if (text.includes("assemble") || text.includes("document") || text.includes("compile")) {
123
+ return "assembly";
124
+ }
125
+ if (text.includes("validate") || text.includes("check")) {
126
+ return "validation";
127
+ }
128
+ if (text.includes("search") || text.includes("find")) {
129
+ return "search";
130
+ }
131
+ if (text.includes("workflow") || text.includes("execute") || text.includes("orchestrat")) {
132
+ return "orchestration";
133
+ }
134
+ return "utility";
135
+ }
136
+ function inferCapabilities(description) {
137
+ const capabilities = [];
138
+ const text = description.toLowerCase();
139
+ for (const { pattern, capability } of CAPABILITY_PATTERNS) {
140
+ if (pattern.test(text)) {
141
+ capabilities.push(capability);
142
+ }
143
+ }
144
+ return capabilities;
145
+ }
146
+ function formatTitle(name) {
147
+ return name.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
148
+ }
149
+ var execAsync = promisify(exec);
150
+ var REGISTRY_VERSION = "1.0.0";
151
+ var DEFAULT_MARKETPLACE_SOURCES = [
152
+ {
153
+ name: "looplia-skills",
154
+ url: "https://github.com/memorysaver/looplia-skills",
155
+ description: "Looplia curated skills collection"
156
+ },
157
+ {
158
+ name: "anthropic-skills",
159
+ url: "https://github.com/anthropics/skills",
160
+ description: "Official Anthropic skills - xlsx, pdf, pptx, docx, frontend-design, and more"
161
+ },
162
+ {
163
+ name: "awesome-claude-skills",
164
+ url: "https://github.com/ComposioHQ/awesome-claude-skills",
165
+ description: "Community-curated Claude skills collection by ComposioHQ"
166
+ }
167
+ ];
70
168
  function getLoopliaHome() {
71
169
  return process.env.LOOPLIA_HOME ?? join(homedir(), ".looplia");
72
170
  }
@@ -86,16 +184,17 @@ async function initializeRegistry(force = false) {
86
184
  await mkdir(registryPath, { recursive: true });
87
185
  await mkdir(join(registryPath, "cache"), { recursive: true });
88
186
  if (force || !await pathExists(sourcesPath)) {
89
- const defaultSources = [
90
- {
91
- id: "official",
92
- type: "official",
93
- url: OFFICIAL_REGISTRY_URL,
187
+ const defaultSources = DEFAULT_MARKETPLACE_SOURCES.map(
188
+ (source, index) => ({
189
+ id: `github:${source.url.replace("https://github.com/", "")}`,
190
+ type: "github",
191
+ url: source.url,
94
192
  enabled: true,
95
- priority: 100,
193
+ priority: 90 - index * 10,
194
+ // First source gets highest priority
96
195
  addedAt: (/* @__PURE__ */ new Date()).toISOString()
97
- }
98
- ];
196
+ })
197
+ );
99
198
  await writeFile(sourcesPath, JSON.stringify(defaultSources, null, 2));
100
199
  }
101
200
  }
@@ -168,7 +267,6 @@ async function tryFetchMarketplace(repoPath) {
168
267
  }
169
268
  }
170
269
  return {
171
- $schema: REGISTRY_SCHEMA_URL,
172
270
  name: marketplace.name,
173
271
  homepage: `https://github.com/${repoPath}`,
174
272
  version: marketplace.version ?? "1.0.0",
@@ -192,24 +290,6 @@ async function tryFetchRegistryJson(repoPath) {
192
290
  }
193
291
  }
194
292
  async function fetchRemoteRegistry(source) {
195
- if (source.type === "official") {
196
- try {
197
- const response = await fetch(source.url);
198
- if (!response.ok) {
199
- console.warn(
200
- `Failed to fetch registry from ${source.url}: ${response.status}`
201
- );
202
- return null;
203
- }
204
- return {
205
- manifest: await response.json(),
206
- format: "registry"
207
- };
208
- } catch (error) {
209
- console.warn(`Error fetching registry from ${source.url}:`, error);
210
- return null;
211
- }
212
- }
213
293
  const repoPath = source.url.replace(PROTOCOL_REGEX, "").replace("github.com/", "").replace(TRAILING_SLASH_REGEX, "");
214
294
  const marketplaceManifest = await tryFetchMarketplace(repoPath);
215
295
  if (marketplaceManifest) {
@@ -224,42 +304,6 @@ async function fetchRemoteRegistry(source) {
224
304
  );
225
305
  return null;
226
306
  }
227
- function parseYamlFrontmatter(frontmatter) {
228
- const lines = frontmatter.split("\n");
229
- const metadata = {};
230
- for (let i = 0; i < lines.length; i++) {
231
- const line = lines[i];
232
- if (line === void 0) {
233
- continue;
234
- }
235
- const colonIndex = line.indexOf(":");
236
- if (colonIndex <= 0) {
237
- continue;
238
- }
239
- const key = line.slice(0, colonIndex).trim();
240
- let value = line.slice(colonIndex + 1).trim();
241
- if (value === "|") {
242
- value = parseMultilineValue(lines, i + 1);
243
- }
244
- metadata[key] = value;
245
- }
246
- return metadata;
247
- }
248
- function parseMultilineValue(lines, startIndex) {
249
- const multilineLines = [];
250
- for (let j = startIndex; j < lines.length; j++) {
251
- const nextLine = lines[j];
252
- if (nextLine === void 0) {
253
- break;
254
- }
255
- if (nextLine.startsWith(" ")) {
256
- multilineLines.push(nextLine.trim());
257
- } else if (nextLine.trim() !== "") {
258
- break;
259
- }
260
- }
261
- return multilineLines.join(" ");
262
- }
263
307
  function buildSkillFromMetadata(metadata) {
264
308
  const category = inferCategory(
265
309
  metadata.name ?? "",
@@ -294,41 +338,6 @@ async function parseSkillMetadata(skillPath) {
294
338
  return null;
295
339
  }
296
340
  }
297
- function inferCategory(name, description) {
298
- const text = `${name} ${description}`.toLowerCase();
299
- if (text.includes("review") || text.includes("analyze") || text.includes("scan")) {
300
- return "analysis";
301
- }
302
- if (text.includes("generate") || text.includes("synthesis") || text.includes("create")) {
303
- return "generation";
304
- }
305
- if (text.includes("assemble") || text.includes("document") || text.includes("compile")) {
306
- return "assembly";
307
- }
308
- if (text.includes("validate") || text.includes("check")) {
309
- return "validation";
310
- }
311
- if (text.includes("search") || text.includes("find")) {
312
- return "search";
313
- }
314
- if (text.includes("workflow") || text.includes("execute") || text.includes("orchestrat")) {
315
- return "orchestration";
316
- }
317
- return "utility";
318
- }
319
- function inferCapabilities(description) {
320
- const capabilities = [];
321
- const text = description.toLowerCase();
322
- for (const { pattern, capability } of CAPABILITY_PATTERNS) {
323
- if (pattern.test(text)) {
324
- capabilities.push(capability);
325
- }
326
- }
327
- return capabilities;
328
- }
329
- function formatTitle(name) {
330
- return name.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
331
- }
332
341
  async function getGitRemoteUrl(repoPath) {
333
342
  const pluginJsonPath = join(repoPath, ".claude-plugin", "plugin.json");
334
343
  try {
@@ -481,10 +490,10 @@ async function processRemoteSource(options) {
481
490
  model: item.model,
482
491
  inputless: item.inputless,
483
492
  source: source.id,
484
- sourceType: source.type === "official" ? "builtin" : "thirdparty",
493
+ sourceType: "thirdparty",
485
494
  installed: installed !== void 0,
486
495
  installedPath: installed?.installedPath,
487
- gitUrl: format === "marketplace" || source.type === "github" ? item.downloadUrl : void 0,
496
+ gitUrl: item.downloadUrl,
488
497
  skillPath: item.skillPath,
489
498
  // Set by marketplace format, undefined for registry.json
490
499
  checksum: item.checksum,
@@ -516,7 +525,8 @@ function buildRegistrySummary(skills) {
516
525
  }
517
526
  return { byCategory, bySource };
518
527
  }
519
- async function compileRegistry(showProgress = false) {
528
+ async function compileRegistry(options) {
529
+ const { showProgress = false, localOnly = true } = options ?? {};
520
530
  const progress = showProgress ? createProgress() : null;
521
531
  const loopliaPath = getLoopliaHome();
522
532
  const sources = await loadSources();
@@ -530,15 +540,17 @@ async function compileRegistry(showProgress = false) {
530
540
  for (const source of localSources) {
531
541
  await processLocalSource(source, seenSkills, allSkills, progress);
532
542
  }
533
- const remoteSources = sources.filter((s) => s.enabled && s.type !== "local").sort((a, b) => b.priority - a.priority);
534
- for (const source of remoteSources) {
535
- await processRemoteSource({
536
- source,
537
- seenSkills,
538
- allSkills,
539
- installedSkillsMap,
540
- progress
541
- });
543
+ if (!localOnly) {
544
+ const remoteSources = sources.filter((s) => s.enabled && s.type !== "local").sort((a, b) => b.priority - a.priority);
545
+ for (const source of remoteSources) {
546
+ await processRemoteSource({
547
+ source,
548
+ seenSkills,
549
+ allSkills,
550
+ installedSkillsMap,
551
+ progress
552
+ });
553
+ }
542
554
  }
543
555
  const { byCategory, bySource } = buildRegistrySummary(allSkills);
544
556
  const compiled = {
@@ -555,10 +567,9 @@ async function compileRegistry(showProgress = false) {
555
567
  }
556
568
  function createEmptyManifest() {
557
569
  return {
558
- $schema: REGISTRY_SCHEMA_URL,
559
- name: "looplia-official",
570
+ name: "looplia",
560
571
  homepage: "https://github.com/memorysaver/looplia-core",
561
- version: "0.7.0",
572
+ version: "0.7.1",
562
573
  updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
563
574
  items: []
564
575
  };
@@ -566,6 +577,10 @@ function createEmptyManifest() {
566
577
 
567
578
  export {
568
579
  createProgress,
580
+ FRONTMATTER_REGEX,
581
+ PROTOCOL_REGEX,
582
+ TRAILING_SLASH_REGEX,
583
+ DEFAULT_MARKETPLACE_SOURCES,
569
584
  getRegistryPath,
570
585
  getCompiledRegistryPath,
571
586
  getSkillCatalogPath,