@larkup/cli 0.2.4 → 0.2.6
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/chunk-VY6I42DP.js +424 -0
- package/dist/index.js +125 -467
- package/dist/tool-loader-QU6HBUCA.js +14 -0
- package/package.json +4 -4
|
@@ -0,0 +1,424 @@
|
|
|
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
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -12,10 +12,17 @@ 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";
|
|
15
23
|
import {
|
|
16
24
|
getAllTools,
|
|
17
|
-
getToolById
|
|
18
|
-
invalidateRegistryCache
|
|
25
|
+
getToolById
|
|
19
26
|
} from "./chunk-P5JVXA7X.js";
|
|
20
27
|
import {
|
|
21
28
|
__require
|
|
@@ -27,7 +34,7 @@ import { Command } from "commander";
|
|
|
27
34
|
// package.json
|
|
28
35
|
var package_default = {
|
|
29
36
|
name: "@larkup/cli",
|
|
30
|
-
version: "0.2.
|
|
37
|
+
version: "0.2.6",
|
|
31
38
|
publishConfig: {
|
|
32
39
|
access: "public"
|
|
33
40
|
},
|
|
@@ -944,12 +951,12 @@ function addChatProviderDependency(dependencies, provider) {
|
|
|
944
951
|
}
|
|
945
952
|
|
|
946
953
|
// ../../packages/core/src/generator/generate-server.ts
|
|
947
|
-
function lang(
|
|
948
|
-
if (
|
|
949
|
-
if (
|
|
950
|
-
if (
|
|
951
|
-
if (
|
|
952
|
-
if (
|
|
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";
|
|
953
960
|
return "text";
|
|
954
961
|
}
|
|
955
962
|
function lancedbStore() {
|
|
@@ -2266,22 +2273,22 @@ function generateServer(config) {
|
|
|
2266
2273
|
{ path: "README.md", contents: readme(config, server) }
|
|
2267
2274
|
].map((f) => ({ ...f, language: lang(f.path) }));
|
|
2268
2275
|
try {
|
|
2269
|
-
const
|
|
2270
|
-
const
|
|
2271
|
-
const faviconPath =
|
|
2272
|
-
if (
|
|
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)) {
|
|
2273
2280
|
files.push({
|
|
2274
2281
|
path: "public/favicon2.ico",
|
|
2275
|
-
contents:
|
|
2282
|
+
contents: fs13.readFileSync(faviconPath).toString("base64"),
|
|
2276
2283
|
language: "ico",
|
|
2277
2284
|
encoding: "base64"
|
|
2278
2285
|
});
|
|
2279
2286
|
} else {
|
|
2280
|
-
const webFaviconPath =
|
|
2281
|
-
if (
|
|
2287
|
+
const webFaviconPath = path14.resolve(process.cwd(), "apps/web/public/favicon2.ico");
|
|
2288
|
+
if (fs13.existsSync(webFaviconPath)) {
|
|
2282
2289
|
files.push({
|
|
2283
2290
|
path: "public/favicon2.ico",
|
|
2284
|
-
contents:
|
|
2291
|
+
contents: fs13.readFileSync(webFaviconPath).toString("base64"),
|
|
2285
2292
|
language: "ico",
|
|
2286
2293
|
encoding: "base64"
|
|
2287
2294
|
});
|
|
@@ -2295,12 +2302,12 @@ function generateServer(config) {
|
|
|
2295
2302
|
}
|
|
2296
2303
|
|
|
2297
2304
|
// ../../packages/core/src/generator/generate-agent-server.ts
|
|
2298
|
-
function lang2(
|
|
2299
|
-
if (
|
|
2300
|
-
if (
|
|
2301
|
-
if (
|
|
2302
|
-
if (
|
|
2303
|
-
if (
|
|
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";
|
|
2304
2311
|
return "text";
|
|
2305
2312
|
}
|
|
2306
2313
|
function lancedbStore2() {
|
|
@@ -3314,22 +3321,22 @@ function generateAgentServer(config) {
|
|
|
3314
3321
|
{ path: "README.md", contents: readme2(config, server) }
|
|
3315
3322
|
].map((f) => ({ ...f, language: lang2(f.path) }));
|
|
3316
3323
|
try {
|
|
3317
|
-
const
|
|
3318
|
-
const
|
|
3319
|
-
const faviconPath =
|
|
3320
|
-
if (
|
|
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)) {
|
|
3321
3328
|
files.push({
|
|
3322
3329
|
path: "public/favicon2.ico",
|
|
3323
|
-
contents:
|
|
3330
|
+
contents: fs13.readFileSync(faviconPath).toString("base64"),
|
|
3324
3331
|
language: "ico",
|
|
3325
3332
|
encoding: "base64"
|
|
3326
3333
|
});
|
|
3327
3334
|
} else {
|
|
3328
|
-
const webFaviconPath =
|
|
3329
|
-
if (
|
|
3335
|
+
const webFaviconPath = path14.resolve(process.cwd(), "apps/web/public/favicon2.ico");
|
|
3336
|
+
if (fs13.existsSync(webFaviconPath)) {
|
|
3330
3337
|
files.push({
|
|
3331
3338
|
path: "public/favicon2.ico",
|
|
3332
|
-
contents:
|
|
3339
|
+
contents: fs13.readFileSync(webFaviconPath).toString("base64"),
|
|
3333
3340
|
language: "ico",
|
|
3334
3341
|
encoding: "base64"
|
|
3335
3342
|
});
|
|
@@ -3406,6 +3413,18 @@ async function writeState(state) {
|
|
|
3406
3413
|
if (file) await fs2.writeFile(file, JSON.stringify(state, null, 2), "utf8");
|
|
3407
3414
|
return state;
|
|
3408
3415
|
}
|
|
3416
|
+
async function withActiveVectorTable(config) {
|
|
3417
|
+
const server = await getActiveServer();
|
|
3418
|
+
if (!server || config.vectorStore && config.vectorStore !== "lancedb") return config;
|
|
3419
|
+
const safeId = server.id.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
3420
|
+
return {
|
|
3421
|
+
...config,
|
|
3422
|
+
storeConfig: {
|
|
3423
|
+
...config.storeConfig,
|
|
3424
|
+
tableName: `documents_${safeId}`
|
|
3425
|
+
}
|
|
3426
|
+
};
|
|
3427
|
+
}
|
|
3409
3428
|
function pidAlive(pid) {
|
|
3410
3429
|
if (!pid) return false;
|
|
3411
3430
|
try {
|
|
@@ -3416,7 +3435,7 @@ function pidAlive(pid) {
|
|
|
3416
3435
|
}
|
|
3417
3436
|
}
|
|
3418
3437
|
async function emitToDisk(config) {
|
|
3419
|
-
const server = generateServer(config);
|
|
3438
|
+
const server = generateServer(await withActiveVectorTable(config));
|
|
3420
3439
|
const dir = await outDir(true);
|
|
3421
3440
|
if (!dir) throw new Error("No active server to emit to.");
|
|
3422
3441
|
await fs2.mkdir(dir, { recursive: true });
|
|
@@ -3452,7 +3471,8 @@ async function startServer(config, serverApiKey) {
|
|
|
3452
3471
|
}
|
|
3453
3472
|
}
|
|
3454
3473
|
await killPort(port);
|
|
3455
|
-
const
|
|
3474
|
+
const runtimeConfig = await withActiveVectorTable(config);
|
|
3475
|
+
const dir = await emitToDisk(runtimeConfig);
|
|
3456
3476
|
try {
|
|
3457
3477
|
await execAsync("npm install --omit=dev", {
|
|
3458
3478
|
cwd: dir,
|
|
@@ -3467,7 +3487,7 @@ async function startServer(config, serverApiKey) {
|
|
|
3467
3487
|
const message = err instanceof Error ? err.message : "npm install failed";
|
|
3468
3488
|
return writeState({ ...emptyState(port), lastError: message });
|
|
3469
3489
|
}
|
|
3470
|
-
const dbPath =
|
|
3490
|
+
const dbPath = runtimeConfig.storeConfig.dbPath || "./.larkup/lancedb";
|
|
3471
3491
|
const absDb = path2.isAbsolute(dbPath) ? dbPath : path2.join(process.cwd(), dbPath);
|
|
3472
3492
|
const logPath = path2.join(dir, "server.log");
|
|
3473
3493
|
await fs2.writeFile(logPath, "", "utf8");
|
|
@@ -3480,35 +3500,35 @@ async function startServer(config, serverApiKey) {
|
|
|
3480
3500
|
env: {
|
|
3481
3501
|
...process.env,
|
|
3482
3502
|
PORT: String(port),
|
|
3483
|
-
TOP_K: String(
|
|
3503
|
+
TOP_K: String(runtimeConfig.topK),
|
|
3484
3504
|
SERVER_API_KEY: serverApiKey || "",
|
|
3485
|
-
EMBEDDING_API_KEY:
|
|
3486
|
-
CHAT_API_KEY:
|
|
3487
|
-
(model) => model.modelName ===
|
|
3505
|
+
EMBEDDING_API_KEY: runtimeConfig.embeddingApiKey || process.env.EMBEDDING_API_KEY || process.env.OPENAI_API_KEY || "",
|
|
3506
|
+
CHAT_API_KEY: runtimeConfig.chatApiKey || runtimeConfig.customChatModels?.find(
|
|
3507
|
+
(model) => model.modelName === runtimeConfig.chatModelId?.replace(/^custom:/, "")
|
|
3488
3508
|
)?.apiKey || process.env.CHAT_API_KEY || process.env.OPENAI_API_KEY || "",
|
|
3489
|
-
CHAT_MODEL: process.env.CHAT_MODEL || resolveChatModel(
|
|
3490
|
-
CHAT_BASE_URL:
|
|
3491
|
-
(model) => model.modelName ===
|
|
3509
|
+
CHAT_MODEL: process.env.CHAT_MODEL || resolveChatModel(runtimeConfig),
|
|
3510
|
+
CHAT_BASE_URL: runtimeConfig.customChatModels?.find(
|
|
3511
|
+
(model) => model.modelName === runtimeConfig.chatModelId?.replace(/^custom:/, "")
|
|
3492
3512
|
)?.baseUrl || process.env.CHAT_BASE_URL || "",
|
|
3493
|
-
OPENAI_API_KEY:
|
|
3494
|
-
ANTHROPIC_API_KEY:
|
|
3495
|
-
COHERE_API_KEY:
|
|
3496
|
-
GOOGLE_GENERATIVE_AI_API_KEY:
|
|
3497
|
-
PINECONE_API_KEY:
|
|
3498
|
-
PINECONE_INDEX:
|
|
3499
|
-
PINECONE_NAMESPACE:
|
|
3500
|
-
PINECONE_SPARSE_MODEL:
|
|
3501
|
-
PINECONE_SPARSE_INDEX:
|
|
3502
|
-
LANCEDB_MODE:
|
|
3513
|
+
OPENAI_API_KEY: runtimeConfig.embeddingApiKey || runtimeConfig.chatApiKey || process.env.OPENAI_API_KEY || "",
|
|
3514
|
+
ANTHROPIC_API_KEY: runtimeConfig.chatApiKey || runtimeConfig.embeddingApiKey || process.env.ANTHROPIC_API_KEY || "",
|
|
3515
|
+
COHERE_API_KEY: runtimeConfig.embeddingApiKey || runtimeConfig.chatApiKey || process.env.COHERE_API_KEY || "",
|
|
3516
|
+
GOOGLE_GENERATIVE_AI_API_KEY: runtimeConfig.embeddingApiKey || runtimeConfig.chatApiKey || process.env.GOOGLE_GENERATIVE_AI_API_KEY || "",
|
|
3517
|
+
PINECONE_API_KEY: runtimeConfig.storeConfig.apiKey || "",
|
|
3518
|
+
PINECONE_INDEX: runtimeConfig.storeConfig.indexName || "",
|
|
3519
|
+
PINECONE_NAMESPACE: runtimeConfig.storeConfig.namespace || "",
|
|
3520
|
+
PINECONE_SPARSE_MODEL: runtimeConfig.storeConfig.sparseModel || "",
|
|
3521
|
+
PINECONE_SPARSE_INDEX: runtimeConfig.storeConfig.sparseIndexName || "",
|
|
3522
|
+
LANCEDB_MODE: runtimeConfig.storeConfig.mode || "local",
|
|
3503
3523
|
LANCEDB_PATH: absDb,
|
|
3504
|
-
LANCEDB_URI:
|
|
3505
|
-
LANCEDB_API_KEY:
|
|
3506
|
-
LANCEDB_S3_URI:
|
|
3507
|
-
AWS_ENDPOINT:
|
|
3508
|
-
AWS_REGION:
|
|
3509
|
-
AWS_ACCESS_KEY_ID:
|
|
3510
|
-
AWS_SECRET_ACCESS_KEY:
|
|
3511
|
-
LANCEDB_TABLE:
|
|
3524
|
+
LANCEDB_URI: runtimeConfig.storeConfig.uri || "",
|
|
3525
|
+
LANCEDB_API_KEY: runtimeConfig.storeConfig.apiKey || "",
|
|
3526
|
+
LANCEDB_S3_URI: runtimeConfig.storeConfig.s3Uri || "",
|
|
3527
|
+
AWS_ENDPOINT: runtimeConfig.storeConfig.s3Endpoint || "",
|
|
3528
|
+
AWS_REGION: runtimeConfig.storeConfig.s3Region || "",
|
|
3529
|
+
AWS_ACCESS_KEY_ID: runtimeConfig.storeConfig.s3AccessKeyId || "",
|
|
3530
|
+
AWS_SECRET_ACCESS_KEY: runtimeConfig.storeConfig.s3SecretAccessKey || "",
|
|
3531
|
+
LANCEDB_TABLE: runtimeConfig.storeConfig.tableName || "documents"
|
|
3512
3532
|
}
|
|
3513
3533
|
});
|
|
3514
3534
|
child.unref();
|
|
@@ -4633,8 +4653,8 @@ async function readTextFiles(files) {
|
|
|
4633
4653
|
}
|
|
4634
4654
|
|
|
4635
4655
|
// src/commands/media.ts
|
|
4636
|
-
import { promises as
|
|
4637
|
-
import
|
|
4656
|
+
import { promises as fs9 } from "fs";
|
|
4657
|
+
import path10 from "path";
|
|
4638
4658
|
|
|
4639
4659
|
// ../../packages/core/src/media-store.ts
|
|
4640
4660
|
import { promises as fs7 } from "fs";
|
|
@@ -4776,406 +4796,44 @@ function claimMediaAsset(id) {
|
|
|
4776
4796
|
});
|
|
4777
4797
|
}
|
|
4778
4798
|
|
|
4779
|
-
// ../../packages/marketplace/src/
|
|
4799
|
+
// ../../packages/marketplace/src/storage-provider.ts
|
|
4780
4800
|
import { promises as fs8 } from "fs";
|
|
4781
4801
|
import path9 from "path";
|
|
4782
|
-
import { exec as execCb } from "child_process";
|
|
4783
|
-
import { promisify as promisify2 } from "util";
|
|
4784
|
-
var execAsync2 = promisify2(execCb);
|
|
4785
|
-
function getToolsDir() {
|
|
4786
|
-
return path9.join(process.cwd(), ".larkup", "tools");
|
|
4787
|
-
}
|
|
4788
|
-
function getManifestPath() {
|
|
4789
|
-
return path9.join(getToolsDir(), "installed.json");
|
|
4790
|
-
}
|
|
4791
|
-
async function ensureDir() {
|
|
4792
|
-
await fs8.mkdir(getToolsDir(), { recursive: true });
|
|
4793
|
-
}
|
|
4794
|
-
async function readManifest() {
|
|
4795
|
-
try {
|
|
4796
|
-
const raw = await fs8.readFile(getManifestPath(), "utf8");
|
|
4797
|
-
const parsed = JSON.parse(raw);
|
|
4798
|
-
if (!parsed.downloadCounts) parsed.downloadCounts = {};
|
|
4799
|
-
for (const tool2 of parsed.tools ?? []) {
|
|
4800
|
-
if (tool2.packagePath && !tool2.packageName) {
|
|
4801
|
-
tool2.packageName = tool2.packagePath;
|
|
4802
|
-
delete tool2.packagePath;
|
|
4803
|
-
}
|
|
4804
|
-
if (!tool2.source) tool2.source = "local";
|
|
4805
|
-
if (!tool2.resolvedPath) {
|
|
4806
|
-
tool2.resolvedPath = tool2.packageName;
|
|
4807
|
-
}
|
|
4808
|
-
}
|
|
4809
|
-
return parsed;
|
|
4810
|
-
} catch {
|
|
4811
|
-
return { tools: [], downloadCounts: {}, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
4812
|
-
}
|
|
4813
|
-
}
|
|
4814
|
-
async function writeManifest(manifest) {
|
|
4815
|
-
await ensureDir();
|
|
4816
|
-
manifest.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4817
|
-
await fs8.writeFile(getManifestPath(), JSON.stringify(manifest, null, 2), "utf8");
|
|
4818
|
-
}
|
|
4819
|
-
async function getInstalledTools() {
|
|
4820
|
-
const manifest = await readManifest();
|
|
4821
|
-
const tools = [...manifest.tools];
|
|
4822
|
-
const bundledIds = (process.env.LARKUP_BUNDLED_TOOLS ?? "").split(",").map((id) => id.trim()).filter(Boolean);
|
|
4823
|
-
for (const toolId of bundledIds) {
|
|
4824
|
-
if (tools.some((tool2) => tool2.id === toolId)) continue;
|
|
4825
|
-
const descriptor = await getToolById(toolId);
|
|
4826
|
-
if (!descriptor) continue;
|
|
4827
|
-
tools.push({
|
|
4828
|
-
id: toolId,
|
|
4829
|
-
version: descriptor.version,
|
|
4830
|
-
installedAt: "bundled",
|
|
4831
|
-
packageName: descriptor.packageName,
|
|
4832
|
-
resolvedPath: descriptor.packageName,
|
|
4833
|
-
source: "local",
|
|
4834
|
-
config: buildDefaultConfig(descriptor)
|
|
4835
|
-
});
|
|
4836
|
-
}
|
|
4837
|
-
return tools;
|
|
4838
|
-
}
|
|
4839
|
-
async function isToolInstalled(toolId) {
|
|
4840
|
-
const tools = await getInstalledTools();
|
|
4841
|
-
return tools.some((t) => t.id === toolId);
|
|
4842
|
-
}
|
|
4843
|
-
async function getInstalledTool(toolId) {
|
|
4844
|
-
const tools = await getInstalledTools();
|
|
4845
|
-
return tools.find((t) => t.id === toolId);
|
|
4846
|
-
}
|
|
4847
|
-
async function checkSystemDeps(toolId) {
|
|
4848
|
-
const descriptor = await getToolById(toolId);
|
|
4849
|
-
if (!descriptor?.systemDeps?.length) return [];
|
|
4850
|
-
const missing = [];
|
|
4851
|
-
for (const dep of descriptor.systemDeps) {
|
|
4852
|
-
try {
|
|
4853
|
-
await execAsync2(`which ${dep}`);
|
|
4854
|
-
} catch {
|
|
4855
|
-
missing.push(dep);
|
|
4856
|
-
}
|
|
4857
|
-
}
|
|
4858
|
-
return missing;
|
|
4859
|
-
}
|
|
4860
|
-
function detectDeploymentTarget() {
|
|
4861
|
-
const explicit = process.env.LARKUP_DEPLOYMENT_TARGET;
|
|
4862
|
-
if (explicit && ["local", "docker", "serverless", "sandbox"].includes(explicit)) {
|
|
4863
|
-
return explicit;
|
|
4864
|
-
}
|
|
4865
|
-
if (process.env.VERCEL || process.env.AWS_LAMBDA_FUNCTION_NAME) return "serverless";
|
|
4866
|
-
if (process.env.DOCKER_CONTAINER || isDockerEnvironment()) return "docker";
|
|
4867
|
-
if (process.env.E2B_SANDBOX_ID || process.env.MODAL_TASK_ID) return "sandbox";
|
|
4868
|
-
return "local";
|
|
4869
|
-
}
|
|
4870
|
-
function isDockerEnvironment() {
|
|
4871
|
-
try {
|
|
4872
|
-
const fs14 = __require("fs");
|
|
4873
|
-
return fs14.existsSync("/.dockerenv");
|
|
4874
|
-
} catch {
|
|
4875
|
-
return false;
|
|
4876
|
-
}
|
|
4877
|
-
}
|
|
4878
|
-
async function ensureToolsPackageJson() {
|
|
4879
|
-
const toolsDir = getToolsDir();
|
|
4880
|
-
const pkgPath = path9.join(toolsDir, "package.json");
|
|
4881
|
-
try {
|
|
4882
|
-
await fs8.access(pkgPath);
|
|
4883
|
-
} catch {
|
|
4884
|
-
await ensureDir();
|
|
4885
|
-
await fs8.writeFile(
|
|
4886
|
-
pkgPath,
|
|
4887
|
-
JSON.stringify(
|
|
4888
|
-
{
|
|
4889
|
-
name: "larkup-tools",
|
|
4890
|
-
version: "1.0.0",
|
|
4891
|
-
private: true,
|
|
4892
|
-
description: "Isolated directory for installed Larkup marketplace tools."
|
|
4893
|
-
},
|
|
4894
|
-
null,
|
|
4895
|
-
2
|
|
4896
|
-
),
|
|
4897
|
-
"utf8"
|
|
4898
|
-
);
|
|
4899
|
-
}
|
|
4900
|
-
}
|
|
4901
|
-
async function execInstall(packageName, version, target, onProgress) {
|
|
4902
|
-
const toolsDir = getToolsDir();
|
|
4903
|
-
switch (target) {
|
|
4904
|
-
case "local":
|
|
4905
|
-
case "docker": {
|
|
4906
|
-
await ensureToolsPackageJson();
|
|
4907
|
-
const install = async (specifier) => {
|
|
4908
|
-
const installCmd = `npm install ${specifier} --prefix "${toolsDir}" --save --no-audit --no-fund`;
|
|
4909
|
-
onProgress?.(`Running: npm install ${specifier}`);
|
|
4910
|
-
const { stderr } = await execAsync2(installCmd, {
|
|
4911
|
-
cwd: toolsDir,
|
|
4912
|
-
timeout: 12e4,
|
|
4913
|
-
// 2 minute timeout
|
|
4914
|
-
env: { ...process.env, NODE_ENV: "production" }
|
|
4915
|
-
});
|
|
4916
|
-
if (stderr && !stderr.includes("npm warn")) {
|
|
4917
|
-
console.warn(`[marketplace] Install stderr: ${stderr}`);
|
|
4918
|
-
}
|
|
4919
|
-
};
|
|
4920
|
-
try {
|
|
4921
|
-
await install(`${packageName}@${version}`);
|
|
4922
|
-
} catch (err) {
|
|
4923
|
-
const message = err instanceof Error ? err.message : "Install command failed";
|
|
4924
|
-
if (!message.includes("ETARGET") && !message.includes("No matching version found")) {
|
|
4925
|
-
throw new Error(`Failed to install ${packageName}: ${message}`);
|
|
4926
|
-
}
|
|
4927
|
-
onProgress?.(
|
|
4928
|
-
`Catalog version ${version} is unavailable; installing the latest published version\u2026`
|
|
4929
|
-
);
|
|
4930
|
-
try {
|
|
4931
|
-
await install(`${packageName}@latest`);
|
|
4932
|
-
} catch (latestErr) {
|
|
4933
|
-
const latestMessage = latestErr instanceof Error ? latestErr.message : "Install command failed";
|
|
4934
|
-
throw new Error(`Failed to install ${packageName}: ${latestMessage}`);
|
|
4935
|
-
}
|
|
4936
|
-
}
|
|
4937
|
-
const resolvedPath = path9.join(toolsDir, "node_modules", packageName);
|
|
4938
|
-
try {
|
|
4939
|
-
await fs8.access(resolvedPath);
|
|
4940
|
-
} catch {
|
|
4941
|
-
throw new Error(
|
|
4942
|
-
`Package ${packageName} was installed but could not be found at ${resolvedPath}`
|
|
4943
|
-
);
|
|
4944
|
-
}
|
|
4945
|
-
const packageJson = JSON.parse(
|
|
4946
|
-
await fs8.readFile(path9.join(resolvedPath, "package.json"), "utf8")
|
|
4947
|
-
);
|
|
4948
|
-
return { resolvedPath, version: packageJson.version ?? version };
|
|
4949
|
-
}
|
|
4950
|
-
case "serverless": {
|
|
4951
|
-
onProgress?.("Serverless environment detected \u2014 queuing for next deploy");
|
|
4952
|
-
const pendingPath = path9.join(toolsDir, "pending-tools.json");
|
|
4953
|
-
let pending = { tools: [] };
|
|
4954
|
-
try {
|
|
4955
|
-
const raw = await fs8.readFile(pendingPath, "utf8");
|
|
4956
|
-
pending = JSON.parse(raw);
|
|
4957
|
-
} catch {
|
|
4958
|
-
}
|
|
4959
|
-
pending.tools.push({ packageName, version });
|
|
4960
|
-
await ensureDir();
|
|
4961
|
-
await fs8.writeFile(pendingPath, JSON.stringify(pending, null, 2), "utf8");
|
|
4962
|
-
return { resolvedPath: path9.join(toolsDir, "node_modules", packageName), version };
|
|
4963
|
-
}
|
|
4964
|
-
case "sandbox": {
|
|
4965
|
-
onProgress?.("Installing in sandbox environment");
|
|
4966
|
-
await ensureToolsPackageJson();
|
|
4967
|
-
const installCmd = `npm install ${packageName}@${version} --prefix "${toolsDir}" --save --no-audit --no-fund`;
|
|
4968
|
-
await execAsync2(installCmd, { cwd: toolsDir, timeout: 12e4 });
|
|
4969
|
-
return { resolvedPath: path9.join(toolsDir, "node_modules", packageName), version };
|
|
4970
|
-
}
|
|
4971
|
-
default:
|
|
4972
|
-
throw new Error(`Unsupported deployment target: ${target}`);
|
|
4973
|
-
}
|
|
4974
|
-
}
|
|
4975
|
-
async function resolveManifest(toolId) {
|
|
4976
|
-
const descriptor = await getToolById(toolId);
|
|
4977
|
-
if (descriptor) return descriptor;
|
|
4978
|
-
throw new Error(`Unknown tool: ${toolId}. Not found in local registry or Hub.`);
|
|
4979
|
-
}
|
|
4980
|
-
async function isWorkspaceTool(packageName) {
|
|
4981
|
-
try {
|
|
4982
|
-
const { stdout } = await execAsync2(`pnpm ls -r --depth -1 --json 2>/dev/null || true`, {
|
|
4983
|
-
cwd: process.cwd(),
|
|
4984
|
-
timeout: 1e4
|
|
4985
|
-
});
|
|
4986
|
-
const data = JSON.parse(stdout || "[]");
|
|
4987
|
-
return Array.isArray(data) && data.some((pkg) => pkg.name === packageName);
|
|
4988
|
-
} catch {
|
|
4989
|
-
return false;
|
|
4990
|
-
}
|
|
4991
|
-
}
|
|
4992
|
-
async function installTool(toolId, onProgress) {
|
|
4993
|
-
const report = (stage, percent, message) => {
|
|
4994
|
-
onProgress?.({ toolId, stage, percent, message });
|
|
4995
|
-
};
|
|
4996
|
-
try {
|
|
4997
|
-
report("checking-deps", 5, "Resolving tool manifest\u2026");
|
|
4998
|
-
const descriptor = await resolveManifest(toolId);
|
|
4999
|
-
if (descriptor.comingSoon) {
|
|
5000
|
-
throw new Error(`${descriptor.name} is coming soon.`);
|
|
5001
|
-
}
|
|
5002
|
-
report("checking-deps", 15, "Checking system dependencies\u2026");
|
|
5003
|
-
const missing = await checkSystemDeps(toolId);
|
|
5004
|
-
if (missing.length > 0) {
|
|
5005
|
-
const msg = `Missing system dependencies: ${missing.join(", ")}. Please install them first.`;
|
|
5006
|
-
report("failed", 0, msg);
|
|
5007
|
-
throw new Error(msg);
|
|
5008
|
-
}
|
|
5009
|
-
const isWorkspace = await isWorkspaceTool(descriptor.packageName);
|
|
5010
|
-
const target = detectDeploymentTarget();
|
|
5011
|
-
let resolvedPath;
|
|
5012
|
-
let installedVersion = descriptor.version;
|
|
5013
|
-
let source;
|
|
5014
|
-
if (isWorkspace) {
|
|
5015
|
-
report("downloading", 30, "Resolving workspace package\u2026");
|
|
5016
|
-
try {
|
|
5017
|
-
const modulePath = __require.resolve(descriptor.packageName, {
|
|
5018
|
-
paths: [process.cwd()]
|
|
5019
|
-
});
|
|
5020
|
-
resolvedPath = path9.dirname(modulePath);
|
|
5021
|
-
} catch {
|
|
5022
|
-
resolvedPath = path9.join(process.cwd(), "node_modules", descriptor.packageName);
|
|
5023
|
-
}
|
|
5024
|
-
source = "local";
|
|
5025
|
-
report("installing", 60, "Workspace package resolved.");
|
|
5026
|
-
} else {
|
|
5027
|
-
report("downloading", 30, `Downloading ${descriptor.packageName}@${descriptor.version}\u2026`);
|
|
5028
|
-
const installed = await execInstall(
|
|
5029
|
-
descriptor.packageName,
|
|
5030
|
-
descriptor.version,
|
|
5031
|
-
target,
|
|
5032
|
-
(msg) => report("downloading", 50, msg)
|
|
5033
|
-
);
|
|
5034
|
-
resolvedPath = installed.resolvedPath;
|
|
5035
|
-
installedVersion = installed.version;
|
|
5036
|
-
source = target === "sandbox" ? "sandbox" : "registry";
|
|
5037
|
-
report("installing", 70, "Package installed.");
|
|
5038
|
-
}
|
|
5039
|
-
report("installing", 80, "Registering tool\u2026");
|
|
5040
|
-
await ensureDir();
|
|
5041
|
-
const manifest = await readManifest();
|
|
5042
|
-
const existing = manifest.tools.findIndex((t) => t.id === toolId);
|
|
5043
|
-
const entry = {
|
|
5044
|
-
id: toolId,
|
|
5045
|
-
version: installedVersion,
|
|
5046
|
-
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5047
|
-
packageName: descriptor.packageName,
|
|
5048
|
-
resolvedPath,
|
|
5049
|
-
source,
|
|
5050
|
-
config: buildDefaultConfig(descriptor)
|
|
5051
|
-
};
|
|
5052
|
-
if (existing >= 0) {
|
|
5053
|
-
manifest.tools[existing] = entry;
|
|
5054
|
-
} else {
|
|
5055
|
-
manifest.tools.push(entry);
|
|
5056
|
-
}
|
|
5057
|
-
manifest.downloadCounts[toolId] = (manifest.downloadCounts[toolId] ?? 0) + 1;
|
|
5058
|
-
await writeManifest(manifest);
|
|
5059
|
-
notifyHubInstall(toolId).catch(() => {
|
|
5060
|
-
});
|
|
5061
|
-
invalidateRegistryCache();
|
|
5062
|
-
report("completed", 100, "Installed successfully.");
|
|
5063
|
-
} catch (err) {
|
|
5064
|
-
const message = err instanceof Error ? err.message : "Installation failed.";
|
|
5065
|
-
report("failed", 0, message);
|
|
5066
|
-
throw err;
|
|
5067
|
-
}
|
|
5068
|
-
}
|
|
5069
|
-
async function uninstallTool(toolId) {
|
|
5070
|
-
const manifest = await readManifest();
|
|
5071
|
-
const tool2 = manifest.tools.find((t) => t.id === toolId);
|
|
5072
|
-
manifest.tools = manifest.tools.filter((t) => t.id !== toolId);
|
|
5073
|
-
await writeManifest(manifest);
|
|
5074
|
-
if (tool2?.source === "registry" && tool2.packageName) {
|
|
5075
|
-
try {
|
|
5076
|
-
const toolsDir = getToolsDir();
|
|
5077
|
-
await execAsync2(`npm uninstall ${tool2.packageName} --prefix "${toolsDir}"`, {
|
|
5078
|
-
cwd: toolsDir,
|
|
5079
|
-
timeout: 3e4
|
|
5080
|
-
});
|
|
5081
|
-
} catch {
|
|
5082
|
-
}
|
|
5083
|
-
}
|
|
5084
|
-
invalidateRegistryCache();
|
|
5085
|
-
}
|
|
5086
|
-
async function notifyHubInstall(toolId) {
|
|
5087
|
-
const hubUrl = process.env.LARKUP_HUB_URL ?? "https://hub.larkup.de";
|
|
5088
|
-
try {
|
|
5089
|
-
const controller = new AbortController();
|
|
5090
|
-
const timeout = setTimeout(() => controller.abort(), 3e3);
|
|
5091
|
-
await fetch(`${hubUrl}/v1/tools/${toolId}/installed`, {
|
|
5092
|
-
method: "POST",
|
|
5093
|
-
signal: controller.signal,
|
|
5094
|
-
headers: { "Content-Type": "application/json" }
|
|
5095
|
-
});
|
|
5096
|
-
clearTimeout(timeout);
|
|
5097
|
-
} catch {
|
|
5098
|
-
}
|
|
5099
|
-
}
|
|
5100
|
-
function buildDefaultConfig(descriptor) {
|
|
5101
|
-
const config = {};
|
|
5102
|
-
for (const field of descriptor.configSchema ?? []) {
|
|
5103
|
-
if (field.defaultValue !== void 0) {
|
|
5104
|
-
config[field.key] = field.defaultValue;
|
|
5105
|
-
}
|
|
5106
|
-
}
|
|
5107
|
-
return config;
|
|
5108
|
-
}
|
|
5109
|
-
|
|
5110
|
-
// ../../packages/marketplace/src/tool-loader.ts
|
|
5111
|
-
var moduleCache = /* @__PURE__ */ new Map();
|
|
5112
|
-
async function loadTool(toolId) {
|
|
5113
|
-
if (moduleCache.has(toolId)) return moduleCache.get(toolId);
|
|
5114
|
-
const installed = await getInstalledTool(toolId);
|
|
5115
|
-
if (!installed) return null;
|
|
5116
|
-
try {
|
|
5117
|
-
const importPath = resolveImportPath(installed);
|
|
5118
|
-
const mod = await import(
|
|
5119
|
-
/* webpackIgnore: true */
|
|
5120
|
-
importPath
|
|
5121
|
-
);
|
|
5122
|
-
moduleCache.set(toolId, mod);
|
|
5123
|
-
return mod;
|
|
5124
|
-
} catch (err) {
|
|
5125
|
-
console.error(`[marketplace] Failed to load tool "${toolId}":`, err);
|
|
5126
|
-
return null;
|
|
5127
|
-
}
|
|
5128
|
-
}
|
|
5129
|
-
function resolveImportPath(installed) {
|
|
5130
|
-
switch (installed.source) {
|
|
5131
|
-
case "local":
|
|
5132
|
-
return installed.packageName;
|
|
5133
|
-
case "registry":
|
|
5134
|
-
case "sandbox":
|
|
5135
|
-
return installed.resolvedPath;
|
|
5136
|
-
default:
|
|
5137
|
-
return installed.packageName;
|
|
5138
|
-
}
|
|
5139
|
-
}
|
|
5140
|
-
|
|
5141
|
-
// ../../packages/marketplace/src/storage-provider.ts
|
|
5142
|
-
import { promises as fs9 } from "fs";
|
|
5143
|
-
import path10 from "path";
|
|
5144
4802
|
var LocalStorageProvider = class {
|
|
5145
4803
|
id = "local";
|
|
5146
4804
|
name = "Local Storage";
|
|
5147
4805
|
async mediaDir() {
|
|
5148
4806
|
const dataDir = await requireDataDir();
|
|
5149
|
-
const dir =
|
|
5150
|
-
await
|
|
4807
|
+
const dir = path9.join(dataDir, "media");
|
|
4808
|
+
await fs8.mkdir(dir, { recursive: true });
|
|
5151
4809
|
return dir;
|
|
5152
4810
|
}
|
|
5153
4811
|
async store(key, data, _mimeType) {
|
|
5154
4812
|
const dir = await this.mediaDir();
|
|
5155
|
-
const filePath =
|
|
5156
|
-
await
|
|
5157
|
-
await
|
|
4813
|
+
const filePath = path9.join(dir, key);
|
|
4814
|
+
await fs8.mkdir(path9.dirname(filePath), { recursive: true });
|
|
4815
|
+
await fs8.writeFile(filePath, data);
|
|
5158
4816
|
return `local://${key}`;
|
|
5159
4817
|
}
|
|
5160
4818
|
async storeFile(key, sourcePath, _mimeType) {
|
|
5161
4819
|
const dir = await this.mediaDir();
|
|
5162
|
-
const filePath =
|
|
5163
|
-
await
|
|
5164
|
-
await
|
|
4820
|
+
const filePath = path9.join(dir, key);
|
|
4821
|
+
await fs8.mkdir(path9.dirname(filePath), { recursive: true });
|
|
4822
|
+
await fs8.copyFile(sourcePath, filePath);
|
|
5165
4823
|
return `local://${key}`;
|
|
5166
4824
|
}
|
|
5167
4825
|
async retrieve(uri) {
|
|
5168
4826
|
const filePath = await this.resolvePath(uri);
|
|
5169
4827
|
if (!filePath) throw new Error(`Unsupported local storage URI: ${uri}`);
|
|
5170
|
-
return
|
|
4828
|
+
return fs8.readFile(filePath);
|
|
5171
4829
|
}
|
|
5172
4830
|
async resolvePath(uri) {
|
|
5173
4831
|
if (!uri.startsWith("local://")) return void 0;
|
|
5174
4832
|
const key = uri.slice("local://".length);
|
|
5175
4833
|
const dir = await this.mediaDir();
|
|
5176
|
-
const filePath =
|
|
5177
|
-
const relative =
|
|
5178
|
-
if (relative.startsWith("..") ||
|
|
4834
|
+
const filePath = path9.resolve(dir, key);
|
|
4835
|
+
const relative = path9.relative(dir, filePath);
|
|
4836
|
+
if (relative.startsWith("..") || path9.isAbsolute(relative)) {
|
|
5179
4837
|
throw new Error("Invalid local storage URI");
|
|
5180
4838
|
}
|
|
5181
4839
|
return filePath;
|
|
@@ -5184,7 +4842,7 @@ var LocalStorageProvider = class {
|
|
|
5184
4842
|
const key = uri.replace("local://", "");
|
|
5185
4843
|
const dir = await this.mediaDir();
|
|
5186
4844
|
try {
|
|
5187
|
-
await
|
|
4845
|
+
await fs8.unlink(path9.join(dir, key));
|
|
5188
4846
|
} catch {
|
|
5189
4847
|
}
|
|
5190
4848
|
}
|
|
@@ -5203,17 +4861,17 @@ async function computeDirStats(dir) {
|
|
|
5203
4861
|
async function walk2(d) {
|
|
5204
4862
|
let entries;
|
|
5205
4863
|
try {
|
|
5206
|
-
entries = await
|
|
4864
|
+
entries = await fs8.readdir(d, { withFileTypes: true });
|
|
5207
4865
|
} catch {
|
|
5208
4866
|
return;
|
|
5209
4867
|
}
|
|
5210
4868
|
for (const entry of entries) {
|
|
5211
|
-
const full =
|
|
4869
|
+
const full = path9.join(d, entry.name);
|
|
5212
4870
|
if (entry.isDirectory()) {
|
|
5213
4871
|
await walk2(full);
|
|
5214
4872
|
} else {
|
|
5215
4873
|
try {
|
|
5216
|
-
const stat = await
|
|
4874
|
+
const stat = await fs8.stat(full);
|
|
5217
4875
|
usedBytes += stat.size;
|
|
5218
4876
|
fileCount++;
|
|
5219
4877
|
} catch {
|
|
@@ -5270,12 +4928,12 @@ async function processMediaCommand(inputs, options) {
|
|
|
5270
4928
|
const assets = await Promise.all(
|
|
5271
4929
|
mediaFiles.map(async (filePath) => {
|
|
5272
4930
|
const type = mediaType(filePath);
|
|
5273
|
-
const stat = await
|
|
5274
|
-
const extension =
|
|
4931
|
+
const stat = await fs9.stat(filePath);
|
|
4932
|
+
const extension = path10.extname(filePath).toLowerCase() || ".bin";
|
|
5275
4933
|
const key = `${type}s/${Date.now()}_${Math.random().toString(36).slice(2)}${extension}`;
|
|
5276
4934
|
const mimeType = MIME_TYPES[extension] || "application/octet-stream";
|
|
5277
|
-
const storageUri = storage.storeFile ? await storage.storeFile(key, filePath, mimeType) : await storage.store(key, await
|
|
5278
|
-
return { type, fileName:
|
|
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 };
|
|
5279
4937
|
})
|
|
5280
4938
|
);
|
|
5281
4939
|
const stored = await addMediaAssets(assets);
|
|
@@ -5357,7 +5015,7 @@ async function processMediaAsset(asset) {
|
|
|
5357
5015
|
if (!tool2.processVideo)
|
|
5358
5016
|
throw new Error("The installed Video & Audio tool cannot process videos.");
|
|
5359
5017
|
await update("Extracting video audio", 20);
|
|
5360
|
-
const outputDir = await
|
|
5018
|
+
const outputDir = await fs9.mkdtemp(path10.join(process.cwd(), ".larkup", "tmp-media-"));
|
|
5361
5019
|
try {
|
|
5362
5020
|
const video = await tool2.processVideo(localFile, {
|
|
5363
5021
|
outputDir,
|
|
@@ -5378,7 +5036,7 @@ async function processMediaAsset(asset) {
|
|
|
5378
5036
|
dimensions = { width: video.meta.width, height: video.meta.height };
|
|
5379
5037
|
frameCount = video.frames.length;
|
|
5380
5038
|
} finally {
|
|
5381
|
-
await
|
|
5039
|
+
await fs9.rm(outputDir, { recursive: true, force: true }).catch(() => {
|
|
5382
5040
|
});
|
|
5383
5041
|
}
|
|
5384
5042
|
} else {
|
|
@@ -5456,7 +5114,7 @@ async function indexPendingMedia() {
|
|
|
5456
5114
|
spinner2.stop(`Indexed ${finalRun.totalChunks} chunks`);
|
|
5457
5115
|
}
|
|
5458
5116
|
function mediaType(filePath) {
|
|
5459
|
-
const extension =
|
|
5117
|
+
const extension = path10.extname(filePath).toLowerCase();
|
|
5460
5118
|
if ([".png", ".jpg", ".jpeg", ".webp", ".gif"].includes(extension)) return "image";
|
|
5461
5119
|
if ([".mp4", ".webm", ".mov", ".mkv"].includes(extension)) return "video";
|
|
5462
5120
|
if ([".mp3", ".m4a", ".wav", ".ogg", ".flac"].includes(extension)) return "audio";
|
|
@@ -5543,20 +5201,20 @@ async function indexCommand(inputs, options) {
|
|
|
5543
5201
|
}
|
|
5544
5202
|
|
|
5545
5203
|
// src/commands/generate.ts
|
|
5546
|
-
import { promises as
|
|
5547
|
-
import
|
|
5204
|
+
import { promises as fs10 } from "fs";
|
|
5205
|
+
import path11 from "path";
|
|
5548
5206
|
async function generateCommand(options) {
|
|
5549
5207
|
await inServerScope(options.server, async () => {
|
|
5550
5208
|
await requireActive();
|
|
5551
5209
|
const config = await readConfig();
|
|
5552
5210
|
if (options.out) {
|
|
5553
|
-
const dir =
|
|
5211
|
+
const dir = path11.isAbsolute(options.out) ? options.out : path11.join(process.cwd(), options.out);
|
|
5554
5212
|
const server2 = generateServer(config);
|
|
5555
|
-
await
|
|
5213
|
+
await fs10.mkdir(dir, { recursive: true });
|
|
5556
5214
|
for (const f of server2.files) {
|
|
5557
|
-
const dest =
|
|
5558
|
-
await
|
|
5559
|
-
await
|
|
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");
|
|
5560
5218
|
}
|
|
5561
5219
|
log.success(`Generated ${server2.files.length} files \u2192 ${dir}`);
|
|
5562
5220
|
} else {
|
|
@@ -5904,8 +5562,8 @@ async function marketplaceCommand(action = "list", toolId) {
|
|
|
5904
5562
|
}
|
|
5905
5563
|
|
|
5906
5564
|
// src/commands/deploy.ts
|
|
5907
|
-
import { promises as
|
|
5908
|
-
import
|
|
5565
|
+
import { promises as fs11 } from "fs";
|
|
5566
|
+
import path12 from "path";
|
|
5909
5567
|
async function deployCommand(target, options) {
|
|
5910
5568
|
await inServerScope(options.server, async () => {
|
|
5911
5569
|
await requireActive();
|
|
@@ -5941,13 +5599,13 @@ async function deployCommand(target, options) {
|
|
|
5941
5599
|
});
|
|
5942
5600
|
}
|
|
5943
5601
|
async function copyGenerated(source, output) {
|
|
5944
|
-
const destination =
|
|
5945
|
-
const relative =
|
|
5946
|
-
if (relative === "" || !relative.startsWith("..") && !
|
|
5602
|
+
const destination = path12.resolve(output);
|
|
5603
|
+
const relative = path12.relative(source, destination);
|
|
5604
|
+
if (relative === "" || !relative.startsWith("..") && !path12.isAbsolute(relative)) {
|
|
5947
5605
|
throw new Error("Deployment output must be outside the generated server directory.");
|
|
5948
5606
|
}
|
|
5949
|
-
await
|
|
5950
|
-
await
|
|
5607
|
+
await fs11.mkdir(destination, { recursive: true });
|
|
5608
|
+
await fs11.cp(source, destination, { recursive: true, force: true });
|
|
5951
5609
|
return destination;
|
|
5952
5610
|
}
|
|
5953
5611
|
|
|
@@ -6032,8 +5690,8 @@ function openCommandForPlatform(url) {
|
|
|
6032
5690
|
}
|
|
6033
5691
|
|
|
6034
5692
|
// src/commands/documents.ts
|
|
6035
|
-
import { promises as
|
|
6036
|
-
import
|
|
5693
|
+
import { promises as fs12 } from "fs";
|
|
5694
|
+
import path13 from "path";
|
|
6037
5695
|
|
|
6038
5696
|
// ../../packages/core/src/corpus-retriever.ts
|
|
6039
5697
|
function applyFilters(docs, filter) {
|
|
@@ -6152,10 +5810,10 @@ async function documentsCommand(action = "list", idOrPath, options) {
|
|
|
6152
5810
|
}
|
|
6153
5811
|
if (action === "export") {
|
|
6154
5812
|
const format = options.format === "jsonl" ? "jsonl" : "csv";
|
|
6155
|
-
const output =
|
|
5813
|
+
const output = path13.resolve(options.out || idOrPath || `corpus.${format}`);
|
|
6156
5814
|
const content = format === "jsonl" ? await exportCorpusAsJSONL(void 0, Number.MAX_SAFE_INTEGER) : await exportCorpusAsCSV(void 0, Number.MAX_SAFE_INTEGER);
|
|
6157
|
-
await
|
|
6158
|
-
await
|
|
5815
|
+
await fs12.mkdir(path13.dirname(output), { recursive: true });
|
|
5816
|
+
await fs12.writeFile(output, content, "utf8");
|
|
6159
5817
|
log.success(`Exported corpus \u2192 ${output}`);
|
|
6160
5818
|
return;
|
|
6161
5819
|
}
|
|
@@ -6181,7 +5839,7 @@ ${document.content}`);
|
|
|
6181
5839
|
return;
|
|
6182
5840
|
}
|
|
6183
5841
|
if (action === "update") {
|
|
6184
|
-
const content = options.file ? await
|
|
5842
|
+
const content = options.file ? await fs12.readFile(path13.resolve(options.file), "utf8") : options.text;
|
|
6185
5843
|
const updated = await updateDocument(document.id, {
|
|
6186
5844
|
title: options.title,
|
|
6187
5845
|
content,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@larkup/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
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/
|
|
32
|
-
"@larkup/
|
|
33
|
-
"@larkup/
|
|
31
|
+
"@larkup/marketplace": "0.1.6",
|
|
32
|
+
"@larkup/vector-stores": "0.1.22",
|
|
33
|
+
"@larkup/core": "0.2.3"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"tsup": "^8.0.0",
|