@larkup/cli 0.2.31 → 0.3.0
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/README.md +11 -1
- package/dist/{dist-es-LRDDK5LI.js → dist-es-3QFDPX44.js} +139 -139
- package/dist/{dist-es-LWW2DNRF.js → dist-es-LH5Y4P7D.js} +3 -3
- package/dist/index.js +225 -23
- package/package.json +15 -12
|
@@ -14,11 +14,11 @@ import {
|
|
|
14
14
|
} from "./chunk-MACWQEJS.js";
|
|
15
15
|
import "./chunk-QGM4M3NI.js";
|
|
16
16
|
|
|
17
|
-
// ../../node_modules/.pnpm/@aws-sdk+s3-request-presigner@3.
|
|
17
|
+
// ../../node_modules/.pnpm/@aws-sdk+s3-request-presigner@3.1127.0/node_modules/@aws-sdk/s3-request-presigner/dist-es/constants.js
|
|
18
18
|
var UNSIGNED_PAYLOAD = "UNSIGNED-PAYLOAD";
|
|
19
19
|
var SHA256_HEADER = "X-Amz-Content-Sha256";
|
|
20
20
|
|
|
21
|
-
// ../../node_modules/.pnpm/@aws-sdk+s3-request-presigner@3.
|
|
21
|
+
// ../../node_modules/.pnpm/@aws-sdk+s3-request-presigner@3.1127.0/node_modules/@aws-sdk/s3-request-presigner/dist-es/presigner.js
|
|
22
22
|
var S3RequestPresigner = class {
|
|
23
23
|
signer;
|
|
24
24
|
constructor(options) {
|
|
@@ -73,7 +73,7 @@ var S3RequestPresigner = class {
|
|
|
73
73
|
}
|
|
74
74
|
};
|
|
75
75
|
|
|
76
|
-
// ../../node_modules/.pnpm/@aws-sdk+s3-request-presigner@3.
|
|
76
|
+
// ../../node_modules/.pnpm/@aws-sdk+s3-request-presigner@3.1127.0/node_modules/@aws-sdk/s3-request-presigner/dist-es/getSignedUrl.js
|
|
77
77
|
var getSignedUrl = async (client, command, options = {}) => {
|
|
78
78
|
let s3Presigner;
|
|
79
79
|
let region;
|
package/dist/index.js
CHANGED
|
@@ -36,7 +36,7 @@ import { Command } from "commander";
|
|
|
36
36
|
// package.json
|
|
37
37
|
var package_default = {
|
|
38
38
|
name: "@larkup/cli",
|
|
39
|
-
version: "0.
|
|
39
|
+
version: "0.3.0",
|
|
40
40
|
engines: {
|
|
41
41
|
node: ">=22"
|
|
42
42
|
},
|
|
@@ -57,25 +57,28 @@ var package_default = {
|
|
|
57
57
|
"type-check": "tsc --noEmit"
|
|
58
58
|
},
|
|
59
59
|
dependencies: {
|
|
60
|
-
"@ai-sdk/cohere": "^4.0.
|
|
61
|
-
"@ai-sdk/deepseek": "^3.0.
|
|
62
|
-
"@ai-sdk/gateway": "^4.0.
|
|
63
|
-
"@ai-sdk/google": "^4.0.
|
|
64
|
-
"@ai-sdk/mistral": "^4.0.
|
|
65
|
-
"@ai-sdk/openai": "^4.0.
|
|
66
|
-
"@ai-sdk/openai-compatible": "^3.0.
|
|
60
|
+
"@ai-sdk/cohere": "^4.0.37",
|
|
61
|
+
"@ai-sdk/deepseek": "^3.0.39",
|
|
62
|
+
"@ai-sdk/gateway": "^4.0.73",
|
|
63
|
+
"@ai-sdk/google": "^4.0.63",
|
|
64
|
+
"@ai-sdk/mistral": "^4.0.39",
|
|
65
|
+
"@ai-sdk/openai": "^4.0.57",
|
|
66
|
+
"@ai-sdk/openai-compatible": "^3.0.43",
|
|
67
67
|
"@clack/prompts": "^1.7.0",
|
|
68
68
|
"@lancedb/lancedb": "^0.38.0",
|
|
69
69
|
"@larkup/core": "workspace:*",
|
|
70
70
|
"@larkup/marketplace": "workspace:*",
|
|
71
71
|
"@larkup/vector-stores": "workspace:*",
|
|
72
|
+
"@napi-rs/canvas": "1.0.8",
|
|
72
73
|
"@pinecone-database/pinecone": "^8.1.0",
|
|
73
|
-
ai: "^7.0.
|
|
74
|
+
ai: "^7.0.91",
|
|
74
75
|
"apache-arrow": "18.1.0",
|
|
75
76
|
chalk: "^6.0.0",
|
|
76
77
|
chromadb: "^3.5.0",
|
|
77
78
|
"cli-table3": "^0.6.5",
|
|
78
79
|
commander: "^15.0.0",
|
|
80
|
+
mammoth: "^1.12.0",
|
|
81
|
+
"pdf-parse": "2.4.5",
|
|
79
82
|
zod: "^4.4.3"
|
|
80
83
|
},
|
|
81
84
|
devDependencies: {
|
|
@@ -4538,6 +4541,8 @@ function providerEnvironmentKey(provider) {
|
|
|
4538
4541
|
// src/lib/local-files.ts
|
|
4539
4542
|
import { promises as fs7 } from "fs";
|
|
4540
4543
|
import path9 from "path";
|
|
4544
|
+
import mammoth from "mammoth";
|
|
4545
|
+
import { getData } from "pdf-parse/worker";
|
|
4541
4546
|
var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
4542
4547
|
".txt",
|
|
4543
4548
|
".md",
|
|
@@ -4569,6 +4574,11 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
4569
4574
|
".sh",
|
|
4570
4575
|
".css"
|
|
4571
4576
|
]);
|
|
4577
|
+
var PDF_EXTENSIONS = /* @__PURE__ */ new Set([".pdf"]);
|
|
4578
|
+
var WORD_EXTENSIONS = /* @__PURE__ */ new Set([".docx"]);
|
|
4579
|
+
var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".webp", ".gif"]);
|
|
4580
|
+
var VIDEO_EXTENSIONS = /* @__PURE__ */ new Set([".mp4", ".webm", ".mov", ".mkv"]);
|
|
4581
|
+
var AUDIO_EXTENSIONS = /* @__PURE__ */ new Set([".mp3", ".m4a", ".wav", ".ogg", ".flac"]);
|
|
4572
4582
|
var MEDIA_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
4573
4583
|
".png",
|
|
4574
4584
|
".jpg",
|
|
@@ -4586,9 +4596,52 @@ var MEDIA_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
4586
4596
|
".flac"
|
|
4587
4597
|
]);
|
|
4588
4598
|
var SKIPPED_DIRECTORIES = /* @__PURE__ */ new Set([".git", ".larkup", "node_modules", "dist", "build"]);
|
|
4599
|
+
var pdfParserPromise;
|
|
4600
|
+
function extensionOf(filePath) {
|
|
4601
|
+
return path9.extname(filePath).toLowerCase();
|
|
4602
|
+
}
|
|
4603
|
+
function normalizedExtension(extension) {
|
|
4604
|
+
const value = extension.trim().toLowerCase();
|
|
4605
|
+
return value ? value.startsWith(".") ? value : `.${value}` : "";
|
|
4606
|
+
}
|
|
4607
|
+
async function getPdfParser() {
|
|
4608
|
+
if (!pdfParserPromise) {
|
|
4609
|
+
pdfParserPromise = (async () => {
|
|
4610
|
+
const canvas = await import("@napi-rs/canvas");
|
|
4611
|
+
Object.assign(globalThis, {
|
|
4612
|
+
DOMMatrix: canvas.DOMMatrix,
|
|
4613
|
+
ImageData: canvas.ImageData,
|
|
4614
|
+
Path2D: canvas.Path2D
|
|
4615
|
+
});
|
|
4616
|
+
const { PDFParse } = await import("pdf-parse");
|
|
4617
|
+
PDFParse.setWorker(getData());
|
|
4618
|
+
return PDFParse;
|
|
4619
|
+
})();
|
|
4620
|
+
}
|
|
4621
|
+
return pdfParserPromise;
|
|
4622
|
+
}
|
|
4589
4623
|
function isMediaPath(filePath) {
|
|
4590
4624
|
return MEDIA_EXTENSIONS.has(path9.extname(filePath).toLowerCase());
|
|
4591
4625
|
}
|
|
4626
|
+
function filterLocalFiles(files, filter = {}) {
|
|
4627
|
+
const requestedExtensions = new Set(
|
|
4628
|
+
(filter.extensions ?? []).map(normalizedExtension).filter(Boolean)
|
|
4629
|
+
);
|
|
4630
|
+
const requestedKinds = new Set(filter.kinds ?? []);
|
|
4631
|
+
if (requestedExtensions.size === 0 && requestedKinds.size === 0) return files;
|
|
4632
|
+
return files.filter((filePath) => {
|
|
4633
|
+
const extension = extensionOf(filePath);
|
|
4634
|
+
if (requestedExtensions.has(extension)) return true;
|
|
4635
|
+
if (requestedKinds.has("media") && MEDIA_EXTENSIONS.has(extension)) return true;
|
|
4636
|
+
if (requestedKinds.has("image") && IMAGE_EXTENSIONS.has(extension)) return true;
|
|
4637
|
+
if (requestedKinds.has("audio") && AUDIO_EXTENSIONS.has(extension)) return true;
|
|
4638
|
+
if (requestedKinds.has("video") && VIDEO_EXTENSIONS.has(extension)) return true;
|
|
4639
|
+
if (requestedKinds.has("pdf") && PDF_EXTENSIONS.has(extension)) return true;
|
|
4640
|
+
if (requestedKinds.has("json") && (extension === ".json" || extension === ".jsonl"))
|
|
4641
|
+
return true;
|
|
4642
|
+
return requestedKinds.has("text") && TEXT_EXTENSIONS.has(extension);
|
|
4643
|
+
});
|
|
4644
|
+
}
|
|
4592
4645
|
async function collectFiles(inputs) {
|
|
4593
4646
|
const files = [];
|
|
4594
4647
|
for (const input of inputs) {
|
|
@@ -4617,8 +4670,22 @@ async function walk(directory, files) {
|
|
|
4617
4670
|
async function readTextFiles(files) {
|
|
4618
4671
|
const documents = [];
|
|
4619
4672
|
for (const filePath of files) {
|
|
4620
|
-
|
|
4621
|
-
|
|
4673
|
+
const extension = extensionOf(filePath);
|
|
4674
|
+
let content;
|
|
4675
|
+
if (PDF_EXTENSIONS.has(extension)) {
|
|
4676
|
+
const PDFParse = await getPdfParser();
|
|
4677
|
+
const parser = new PDFParse({ data: new Uint8Array(await fs7.readFile(filePath)) });
|
|
4678
|
+
try {
|
|
4679
|
+
content = (await parser.getText()).text;
|
|
4680
|
+
} finally {
|
|
4681
|
+
await parser.destroy();
|
|
4682
|
+
}
|
|
4683
|
+
} else if (WORD_EXTENSIONS.has(extension)) {
|
|
4684
|
+
content = (await mammoth.extractRawText({ buffer: await fs7.readFile(filePath) })).value;
|
|
4685
|
+
} else {
|
|
4686
|
+
if (!TEXT_EXTENSIONS.has(extension)) continue;
|
|
4687
|
+
content = await fs7.readFile(filePath, "utf8");
|
|
4688
|
+
}
|
|
4622
4689
|
if (!content.trim() || content.includes("\0")) continue;
|
|
4623
4690
|
documents.push({
|
|
4624
4691
|
path: filePath,
|
|
@@ -4886,7 +4953,7 @@ var S3StorageProvider = class {
|
|
|
4886
4953
|
}
|
|
4887
4954
|
async client() {
|
|
4888
4955
|
if (!this._client) {
|
|
4889
|
-
const { S3Client } = await import("./dist-es-
|
|
4956
|
+
const { S3Client } = await import("./dist-es-3QFDPX44.js");
|
|
4890
4957
|
this._client = new S3Client({
|
|
4891
4958
|
region: this.region,
|
|
4892
4959
|
...this._credentials ? { credentials: this._credentials } : {}
|
|
@@ -4905,7 +4972,7 @@ var S3StorageProvider = class {
|
|
|
4905
4972
|
return { bucket: withoutScheme.slice(0, slashIndex), key: withoutScheme.slice(slashIndex + 1) };
|
|
4906
4973
|
}
|
|
4907
4974
|
async store(key, data, mimeType) {
|
|
4908
|
-
const { PutObjectCommand } = await import("./dist-es-
|
|
4975
|
+
const { PutObjectCommand } = await import("./dist-es-3QFDPX44.js");
|
|
4909
4976
|
const client = await this.client();
|
|
4910
4977
|
const objectKey = this.objectKey(key);
|
|
4911
4978
|
await client.send(
|
|
@@ -4923,7 +4990,7 @@ var S3StorageProvider = class {
|
|
|
4923
4990
|
return this.store(key, await fs9.readFile(sourcePath), mimeType);
|
|
4924
4991
|
}
|
|
4925
4992
|
async retrieve(uri) {
|
|
4926
|
-
const { GetObjectCommand } = await import("./dist-es-
|
|
4993
|
+
const { GetObjectCommand } = await import("./dist-es-3QFDPX44.js");
|
|
4927
4994
|
const { bucket, key } = this.parseUri(uri);
|
|
4928
4995
|
const client = await this.client();
|
|
4929
4996
|
const response = await client.send(new GetObjectCommand({ Bucket: bucket, Key: key }));
|
|
@@ -4939,8 +5006,8 @@ var S3StorageProvider = class {
|
|
|
4939
5006
|
return void 0;
|
|
4940
5007
|
}
|
|
4941
5008
|
async getReadUrl(uri, expiresInSecs) {
|
|
4942
|
-
const { GetObjectCommand } = await import("./dist-es-
|
|
4943
|
-
const { getSignedUrl } = await import("./dist-es-
|
|
5009
|
+
const { GetObjectCommand } = await import("./dist-es-3QFDPX44.js");
|
|
5010
|
+
const { getSignedUrl } = await import("./dist-es-LH5Y4P7D.js");
|
|
4944
5011
|
const { bucket, key } = this.parseUri(uri);
|
|
4945
5012
|
const client = await this.client();
|
|
4946
5013
|
return getSignedUrl(client, new GetObjectCommand({ Bucket: bucket, Key: key }), {
|
|
@@ -4948,7 +5015,7 @@ var S3StorageProvider = class {
|
|
|
4948
5015
|
});
|
|
4949
5016
|
}
|
|
4950
5017
|
async delete(uri) {
|
|
4951
|
-
const { DeleteObjectCommand } = await import("./dist-es-
|
|
5018
|
+
const { DeleteObjectCommand } = await import("./dist-es-3QFDPX44.js");
|
|
4952
5019
|
const { bucket, key } = this.parseUri(uri);
|
|
4953
5020
|
const client = await this.client();
|
|
4954
5021
|
try {
|
|
@@ -5897,13 +5964,34 @@ function deriveCliAudioSignals(chunks) {
|
|
|
5897
5964
|
}
|
|
5898
5965
|
|
|
5899
5966
|
// src/commands/index-cmd.ts
|
|
5967
|
+
function selectedKinds(options) {
|
|
5968
|
+
return [
|
|
5969
|
+
...options.pdf ? ["pdf"] : [],
|
|
5970
|
+
...options.json ? ["json"] : [],
|
|
5971
|
+
...options.media ? ["media"] : [],
|
|
5972
|
+
...options.image ? ["image"] : [],
|
|
5973
|
+
...options.audio ? ["audio"] : [],
|
|
5974
|
+
...options.video ? ["video"] : []
|
|
5975
|
+
];
|
|
5976
|
+
}
|
|
5977
|
+
function progressBar(current, total) {
|
|
5978
|
+
if (total <= 0) return "Preparing chunks";
|
|
5979
|
+
const width = 24;
|
|
5980
|
+
const completed = Math.min(width, Math.round(current / total * width));
|
|
5981
|
+
const percentage = Math.min(100, Math.round(current / total * 100));
|
|
5982
|
+
return `[${"\u2588".repeat(completed)}${"\u2591".repeat(width - completed)}] ${percentage}%`;
|
|
5983
|
+
}
|
|
5900
5984
|
async function indexCommand(inputs, options) {
|
|
5901
5985
|
await inProjectScope(options.project, async () => {
|
|
5902
5986
|
await requireActiveProject();
|
|
5903
5987
|
if (inputs.length > 0) {
|
|
5904
5988
|
const files = await collectFiles(inputs);
|
|
5905
|
-
const
|
|
5906
|
-
|
|
5989
|
+
const selected = filterLocalFiles(files, {
|
|
5990
|
+
kinds: selectedKinds(options),
|
|
5991
|
+
extensions: options.extension?.split(",")
|
|
5992
|
+
});
|
|
5993
|
+
const textFiles = await readTextFiles(selected);
|
|
5994
|
+
const mediaFiles = selected.filter(isMediaPath);
|
|
5907
5995
|
for (const document of textFiles) {
|
|
5908
5996
|
await addDocument({ title: document.title, content: document.content, source: "files" });
|
|
5909
5997
|
}
|
|
@@ -5939,7 +6027,9 @@ async function indexCommand(inputs, options) {
|
|
|
5939
6027
|
const r = await readRun();
|
|
5940
6028
|
if (!r || done) return;
|
|
5941
6029
|
if (r.totalChunks > 0) {
|
|
5942
|
-
s.message(
|
|
6030
|
+
s.message(
|
|
6031
|
+
`${r.status.padEnd(10)} ${progressBar(r.processedChunks, r.totalChunks)} ${r.processedChunks}/${r.totalChunks} chunks`
|
|
6032
|
+
);
|
|
5943
6033
|
} else {
|
|
5944
6034
|
s.message(`${r.status}\u2026`);
|
|
5945
6035
|
}
|
|
@@ -6218,8 +6308,8 @@ async function chatCommand(options) {
|
|
|
6218
6308
|
const provider = config.chatProvider || config.embeddingProvider;
|
|
6219
6309
|
const chatModels = (await getAllModels()).filter((model) => model.type === "language").map(toChatDescriptor);
|
|
6220
6310
|
const chatModelId = options.model || config.chatModelId || getDefaultChatModel(chatModels, provider)?.id || "openai/gpt-4o-mini";
|
|
6221
|
-
const
|
|
6222
|
-
if (provider !== "vercel_ai_gateway" &&
|
|
6311
|
+
const modelProvider2 = chatModelId.startsWith("custom:") ? "custom" : chatModelId.includes("/") ? chatModelId.split("/", 1)[0] : provider;
|
|
6312
|
+
if (provider !== "vercel_ai_gateway" && modelProvider2 !== provider) {
|
|
6223
6313
|
throw new Error(
|
|
6224
6314
|
`Model "${chatModelId}" is not available through the configured ${provider} provider. Choose a matching model or change the chat provider with \`larkup settings\`.`
|
|
6225
6315
|
);
|
|
@@ -6954,6 +7044,101 @@ async function installCommand(options) {
|
|
|
6954
7044
|
if (notEntitled.length) log.error(`Not entitled for this organization: ${notEntitled.join(", ")}`);
|
|
6955
7045
|
}
|
|
6956
7046
|
|
|
7047
|
+
// src/commands/ai-model.ts
|
|
7048
|
+
function modelProvider(modelId) {
|
|
7049
|
+
return modelId.split("/")[0] || "openai";
|
|
7050
|
+
}
|
|
7051
|
+
function supportsVision(model) {
|
|
7052
|
+
return model.type === "language" && Boolean(model.tags?.includes("vision"));
|
|
7053
|
+
}
|
|
7054
|
+
function printModel(model) {
|
|
7055
|
+
log.info(`${model.id}${model.name && model.name !== model.id ? ` ${model.name}` : ""}`);
|
|
7056
|
+
if (model.description) log.dim(` ${model.description}`);
|
|
7057
|
+
}
|
|
7058
|
+
async function listModels(type) {
|
|
7059
|
+
const models = await getAllModels();
|
|
7060
|
+
const selectedType = type ?? "embedding";
|
|
7061
|
+
if (selectedType === "embedding") {
|
|
7062
|
+
for (const model of EMBEDDING_MODELS) printModel({ ...model, name: model.label });
|
|
7063
|
+
return;
|
|
7064
|
+
}
|
|
7065
|
+
const matching = models.filter(
|
|
7066
|
+
selectedType === "vision" ? supportsVision : (model) => model.type === "language" && model.tags?.includes("tool-use")
|
|
7067
|
+
);
|
|
7068
|
+
for (const model of matching) printModel(model);
|
|
7069
|
+
}
|
|
7070
|
+
function validateLanguageModel(models, modelId, capability) {
|
|
7071
|
+
const model = models.find((candidate) => candidate.id === modelId);
|
|
7072
|
+
if (!model || model.type !== "language") {
|
|
7073
|
+
throw new Error(
|
|
7074
|
+
`Unknown ${capability} model "${modelId}". Run: larkup ai-model list --type ${capability}`
|
|
7075
|
+
);
|
|
7076
|
+
}
|
|
7077
|
+
if (capability === "vision" && !supportsVision(model)) {
|
|
7078
|
+
throw new Error(
|
|
7079
|
+
`Model "${modelId}" is not vision-capable. Run: larkup ai-model list --type vision`
|
|
7080
|
+
);
|
|
7081
|
+
}
|
|
7082
|
+
return model;
|
|
7083
|
+
}
|
|
7084
|
+
async function aiModelCommand(action, options) {
|
|
7085
|
+
await inProjectScope(options.project, async () => {
|
|
7086
|
+
await requireActiveProject();
|
|
7087
|
+
if (action === "list") {
|
|
7088
|
+
await listModels(options.type);
|
|
7089
|
+
return;
|
|
7090
|
+
}
|
|
7091
|
+
if (action && action !== "show") {
|
|
7092
|
+
throw new Error(
|
|
7093
|
+
`Unknown ai-model action "${action}". Use "list" or omit the action to configure models.`
|
|
7094
|
+
);
|
|
7095
|
+
}
|
|
7096
|
+
const config = await readConfig();
|
|
7097
|
+
const apiKey = options.apiKey ?? options.apikey;
|
|
7098
|
+
if (!options.embedding && !options.chat && !options.vision) {
|
|
7099
|
+
if (apiKey) {
|
|
7100
|
+
await writeConfig({ ...config, embeddingApiKey: apiKey });
|
|
7101
|
+
log.success("Embedding API key saved for the active Project.");
|
|
7102
|
+
return;
|
|
7103
|
+
}
|
|
7104
|
+
log.info(`Embedding ${config.embeddingModelId}`);
|
|
7105
|
+
log.info(`Chat ${config.chatModelId ?? "not configured"}`);
|
|
7106
|
+
log.info(`Vision ${config.visionModelId ?? "not configured"}`);
|
|
7107
|
+
log.dim(
|
|
7108
|
+
"Set one with: larkup ai-model --embedding openai/text-embedding-3-small --api-key <key>"
|
|
7109
|
+
);
|
|
7110
|
+
return;
|
|
7111
|
+
}
|
|
7112
|
+
const models = await getAllModels();
|
|
7113
|
+
const next = { ...config };
|
|
7114
|
+
if (options.embedding) {
|
|
7115
|
+
const embedding = getEmbeddingModel(options.embedding);
|
|
7116
|
+
if (!embedding) {
|
|
7117
|
+
throw new Error(
|
|
7118
|
+
`Unknown embedding model "${options.embedding}". Run: larkup ai-model list --type embedding`
|
|
7119
|
+
);
|
|
7120
|
+
}
|
|
7121
|
+
next.embeddingModelId = embedding.id;
|
|
7122
|
+
next.embeddingProvider = embedding.provider;
|
|
7123
|
+
if (apiKey) next.embeddingApiKey = apiKey;
|
|
7124
|
+
}
|
|
7125
|
+
if (options.chat) {
|
|
7126
|
+
const chat = validateLanguageModel(models, options.chat, "chat");
|
|
7127
|
+
next.chatModelId = chat.id;
|
|
7128
|
+
next.chatProvider = modelProvider(chat.id);
|
|
7129
|
+
if (apiKey) next.chatApiKey = apiKey;
|
|
7130
|
+
}
|
|
7131
|
+
if (options.vision) {
|
|
7132
|
+
const vision = validateLanguageModel(models, options.vision, "vision");
|
|
7133
|
+
next.visionModelId = vision.id;
|
|
7134
|
+
next.visionProvider = modelProvider(vision.id);
|
|
7135
|
+
if (apiKey) next.visionApiKey = apiKey;
|
|
7136
|
+
}
|
|
7137
|
+
await writeConfig(next);
|
|
7138
|
+
log.success("AI model settings saved. The Web UI now uses the same Project configuration.");
|
|
7139
|
+
});
|
|
7140
|
+
}
|
|
7141
|
+
|
|
6957
7142
|
// src/index.ts
|
|
6958
7143
|
var program = new Command();
|
|
6959
7144
|
program.name("larkup").description("Build, index, and serve a RAG pipeline from the terminal.").version(package_default.version);
|
|
@@ -6985,9 +7170,26 @@ program.command("add-doc").description("Add a document to the corpus").option("-
|
|
|
6985
7170
|
program.command("documents [action] [idOrPath]").alias("docs").description("List, show, update, remove, or export corpus documents").option("--title <title>", "Set a document title when updating").option("--text <content>", "Set document content when updating").option("--file <path>", "Read updated document content from a file").option("--url <url>", "Set the source URL when updating").option("--format <csv|jsonl>", "Corpus export format", "csv").option("--out <path>", "Corpus export destination").option("--project <id>", "Target a specific Project instead of the active one").action(async (action, idOrPath, options) => {
|
|
6986
7171
|
await documentsCommand(action, idOrPath, options);
|
|
6987
7172
|
});
|
|
6988
|
-
program.command("index [sources...]").description("Load files or folders, then chunk \u2192 embed \u2192 store the corpus").option("--project <id>", "Target a specific Project instead of the active one").option("--no-run", "Load supplied sources without building the index").option("--incremental", "Index only documents added since the last completed run").action(async (sources, options) => {
|
|
7173
|
+
program.command("index [sources...]").description("Load files or folders, then chunk \u2192 embed \u2192 store the corpus").option("--project <id>", "Target a specific Project instead of the active one").option("--no-run", "Load supplied sources without building the index").option("--incremental", "Index only documents added since the last completed run").option("--pdf", "Index PDF files only").option("--json", "Index JSON and JSONL files only").option("--media", "Index images, audio, and video only").option("--image", "Index image files only").option("--audio", "Index audio files only").option("--video", "Index video files only").option("--extension <extensions>", "Comma-separated extensions, for example .json,.pdf").action(async (sources, options) => {
|
|
7174
|
+
await indexCommand(sources ?? [], options);
|
|
7175
|
+
});
|
|
7176
|
+
program.command("indexing [sources...]").description("Alias for index").option("--project <id>", "Target a specific Project instead of the active one").option("--no-run", "Load supplied sources without building the index").option("--incremental", "Index only documents added since the last completed run").option("--pdf", "Index PDF files only").option("--json", "Index JSON and JSONL files only").option("--media", "Index images, audio, and video only").option("--image", "Index image files only").option("--audio", "Index audio files only").option("--video", "Index video files only").option("--extension <extensions>", "Comma-separated extensions, for example .json,.pdf").action(async (sources, options) => {
|
|
6989
7177
|
await indexCommand(sources ?? [], options);
|
|
6990
7178
|
});
|
|
7179
|
+
function configureAiModelCommand(command) {
|
|
7180
|
+
return command.option("--embedding <model>", "Set the embedding model ID").option("--chat <model>", "Set the chat model ID").option("--vision <model>", "Set the vision model ID").option("--api-key <key>", "Set the API key for the selected model type(s)").option("--apikey <key>", "Alias for --api-key").option("--project <id>", "Target a specific Project instead of the active one").option("--type <embedding|chat|vision>", "Filter model list by capability");
|
|
7181
|
+
}
|
|
7182
|
+
configureAiModelCommand(
|
|
7183
|
+
program.command("ai-model [action]").description("List or configure embedding, chat, and vision AI models")
|
|
7184
|
+
).action(async (action, options) => {
|
|
7185
|
+
await aiModelCommand(action, options);
|
|
7186
|
+
});
|
|
7187
|
+
var setCommand = program.command("set").description("Set Project configuration values");
|
|
7188
|
+
configureAiModelCommand(
|
|
7189
|
+
setCommand.command("ai-model").description("Configure AI models (alias for ai-model)")
|
|
7190
|
+
).action(async (options) => {
|
|
7191
|
+
await aiModelCommand(void 0, options);
|
|
7192
|
+
});
|
|
6991
7193
|
program.command("media [sources...]").description("Add image, audio, or video files and stream processing progress").option("--no-index", "Process media without rebuilding the index").option("--project <id>", "Target a specific Project instead of the active one").action(async (sources, options) => {
|
|
6992
7194
|
await mediaCommand(sources ?? [], options);
|
|
6993
7195
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@larkup/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=22"
|
|
6
6
|
},
|
|
@@ -15,26 +15,29 @@
|
|
|
15
15
|
"dist"
|
|
16
16
|
],
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@ai-sdk/cohere": "^4.0.
|
|
19
|
-
"@ai-sdk/deepseek": "^3.0.
|
|
20
|
-
"@ai-sdk/gateway": "^4.0.
|
|
21
|
-
"@ai-sdk/google": "^4.0.
|
|
22
|
-
"@ai-sdk/mistral": "^4.0.
|
|
23
|
-
"@ai-sdk/openai": "^4.0.
|
|
24
|
-
"@ai-sdk/openai-compatible": "^3.0.
|
|
18
|
+
"@ai-sdk/cohere": "^4.0.37",
|
|
19
|
+
"@ai-sdk/deepseek": "^3.0.39",
|
|
20
|
+
"@ai-sdk/gateway": "^4.0.73",
|
|
21
|
+
"@ai-sdk/google": "^4.0.63",
|
|
22
|
+
"@ai-sdk/mistral": "^4.0.39",
|
|
23
|
+
"@ai-sdk/openai": "^4.0.57",
|
|
24
|
+
"@ai-sdk/openai-compatible": "^3.0.43",
|
|
25
25
|
"@clack/prompts": "^1.7.0",
|
|
26
26
|
"@lancedb/lancedb": "^0.38.0",
|
|
27
|
+
"@napi-rs/canvas": "1.0.8",
|
|
27
28
|
"@pinecone-database/pinecone": "^8.1.0",
|
|
28
|
-
"ai": "^7.0.
|
|
29
|
+
"ai": "^7.0.91",
|
|
29
30
|
"apache-arrow": "18.1.0",
|
|
30
31
|
"chalk": "^6.0.0",
|
|
31
32
|
"chromadb": "^3.5.0",
|
|
32
33
|
"cli-table3": "^0.6.5",
|
|
33
34
|
"commander": "^15.0.0",
|
|
35
|
+
"mammoth": "^1.12.0",
|
|
36
|
+
"pdf-parse": "2.4.5",
|
|
34
37
|
"zod": "^4.4.3",
|
|
35
|
-
"@larkup/core": "0.5.
|
|
36
|
-
"@larkup/
|
|
37
|
-
"@larkup/
|
|
38
|
+
"@larkup/core": "0.5.4",
|
|
39
|
+
"@larkup/vector-stores": "0.1.27",
|
|
40
|
+
"@larkup/marketplace": "0.2.4"
|
|
38
41
|
},
|
|
39
42
|
"devDependencies": {
|
|
40
43
|
"tsup": "^8.5.1",
|