alys-akusa 0.1.2 → 0.1.4
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 +1 -1
- package/dist/index.cjs +252 -53
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -4908,6 +4908,8 @@ var CONFIG_DIR = import_node_path.default.join(import_node_os.default.homedir(),
|
|
|
4908
4908
|
var CONFIG_PATH = import_node_path.default.join(CONFIG_DIR, "config.json");
|
|
4909
4909
|
var ALYS_APP_URL = process.env.ALYS_APP_URL || process.env.NEXT_PUBLIC_SITE_URL || "https://alys.akusa.dev";
|
|
4910
4910
|
var MAX_DATASETS_PER_RUN = 5;
|
|
4911
|
+
var MAX_SOURCES_PER_RUN = 8;
|
|
4912
|
+
var MAX_ROWS_PER_DATASET = 125;
|
|
4911
4913
|
var FIGLET_LOGO = [
|
|
4912
4914
|
" o ooooo ooooo oooo oooooooo8 ",
|
|
4913
4915
|
" 888 888 888 88 888 ",
|
|
@@ -4928,6 +4930,8 @@ function printBanner() {
|
|
|
4928
4930
|
function printHelp() {
|
|
4929
4931
|
printBanner();
|
|
4930
4932
|
console.log(`
|
|
4933
|
+
Alys runs in your terminal. The dashboard tracks what it generates.
|
|
4934
|
+
|
|
4931
4935
|
Usage:
|
|
4932
4936
|
npx alys-akusa
|
|
4933
4937
|
npx alys-akusa login
|
|
@@ -4940,8 +4944,8 @@ Flags:
|
|
|
4940
4944
|
--type instruction|rag|qa
|
|
4941
4945
|
--datasets 1
|
|
4942
4946
|
--depth shallow|medium|deep
|
|
4943
|
-
--sources
|
|
4944
|
-
--rows
|
|
4947
|
+
--sources 8
|
|
4948
|
+
--rows 125
|
|
4945
4949
|
--workspace ~/Desktop/alys-output
|
|
4946
4950
|
--verify
|
|
4947
4951
|
--no-verify
|
|
@@ -5014,7 +5018,7 @@ async function requestJson(pathname, init = {}, token) {
|
|
|
5014
5018
|
const response = await fetch(apiUrl(pathname), { ...init, headers });
|
|
5015
5019
|
const payload = await response.json().catch(() => ({}));
|
|
5016
5020
|
if (!response.ok) {
|
|
5017
|
-
const message = typeof payload?.error === "string" ? payload.error : `Alys
|
|
5021
|
+
const message = typeof payload?.error === "string" ? payload.error : `Alys request failed (${response.status}).`;
|
|
5018
5022
|
throw new CliApiError(message, response.status, payload);
|
|
5019
5023
|
}
|
|
5020
5024
|
return payload;
|
|
@@ -5078,6 +5082,19 @@ function parseDepth(value) {
|
|
|
5078
5082
|
if (value === "shallow" || value === "medium" || value === "deep") return value;
|
|
5079
5083
|
return void 0;
|
|
5080
5084
|
}
|
|
5085
|
+
function normalizeTopicInput(value) {
|
|
5086
|
+
if (typeof value !== "string") return "";
|
|
5087
|
+
let topic = value.replace(/\[[^\]]+\][^\n\r]*/g, "").replace(/\s+/g, " ").trim();
|
|
5088
|
+
const commandMatch = topic.match(/^(?:npx\s+)?(?:alys-akusa(?:@latest)?|alys)\s+generate\s+(.+)$/i);
|
|
5089
|
+
if (commandMatch) {
|
|
5090
|
+
topic = commandMatch[1].trim();
|
|
5091
|
+
}
|
|
5092
|
+
const quoted = topic.match(/^"([^"]+)"|^'([^']+)'/);
|
|
5093
|
+
if (quoted) {
|
|
5094
|
+
return (quoted[1] || quoted[2] || "").trim();
|
|
5095
|
+
}
|
|
5096
|
+
return topic.replace(/\s+--(?:format|type|datasets|depth|sources|rows|workspace)\s+\S.*$/i, "").replace(/\s+--(?:verify|no-verify|yes)\b.*$/i, "").trim();
|
|
5097
|
+
}
|
|
5081
5098
|
function resolveHome(p) {
|
|
5082
5099
|
if (p.startsWith("~/")) return import_node_path.default.join(import_node_os.default.homedir(), p.slice(2));
|
|
5083
5100
|
return p;
|
|
@@ -5085,14 +5102,94 @@ function resolveHome(p) {
|
|
|
5085
5102
|
function formatInt(value) {
|
|
5086
5103
|
return new Intl.NumberFormat("en-US").format(value);
|
|
5087
5104
|
}
|
|
5105
|
+
function formatPercent(value) {
|
|
5106
|
+
if (!Number.isFinite(value) || value <= 0) return "pending";
|
|
5107
|
+
return `${Math.round(value * 100)}%`;
|
|
5108
|
+
}
|
|
5109
|
+
function formatScore(value) {
|
|
5110
|
+
if (!Number.isFinite(value) || value <= 0) return "pending";
|
|
5111
|
+
return `${Math.round(value)}/100`;
|
|
5112
|
+
}
|
|
5113
|
+
function average(values) {
|
|
5114
|
+
const filtered = values.filter((value) => Number.isFinite(value) && value > 0);
|
|
5115
|
+
return filtered.length ? filtered.reduce((sum, value) => sum + value, 0) / filtered.length : 0;
|
|
5116
|
+
}
|
|
5117
|
+
function truncate(value, max = 88) {
|
|
5118
|
+
const normalized = value.replace(/\s+/g, " ").trim();
|
|
5119
|
+
return normalized.length > max ? `${normalized.slice(0, max - 1)}\u2026` : normalized;
|
|
5120
|
+
}
|
|
5121
|
+
function getMetrics(dataset) {
|
|
5122
|
+
const metrics = dataset.manifest.metrics;
|
|
5123
|
+
return metrics && typeof metrics === "object" ? metrics : {};
|
|
5124
|
+
}
|
|
5125
|
+
function getSummary(dataset) {
|
|
5126
|
+
const summary = dataset.manifest.generationSummary;
|
|
5127
|
+
return summary && typeof summary === "object" ? summary : {};
|
|
5128
|
+
}
|
|
5129
|
+
function getQualityMetrics(dataset) {
|
|
5130
|
+
const metrics = dataset.manifest.qualityMetrics;
|
|
5131
|
+
return metrics && typeof metrics === "object" ? metrics : {};
|
|
5132
|
+
}
|
|
5133
|
+
function getEvaluation(dataset) {
|
|
5134
|
+
const evaluation = dataset.manifest.evaluation;
|
|
5135
|
+
return evaluation && typeof evaluation === "object" ? evaluation : {};
|
|
5136
|
+
}
|
|
5137
|
+
function printStage(code, status, label, metric) {
|
|
5138
|
+
const tint = status === "DONE" || status === "OK" ? "green" : status === "WARN" ? "yellow" : "cyan";
|
|
5139
|
+
const prefix = `${paint(`[${code.padEnd(4).slice(0, 4)}]`, "gray")} ${paint(status.padEnd(4), tint)}`;
|
|
5140
|
+
console.log(`${prefix} ${label}${metric ? ` ${paint(metric, "gray")}` : ""}`);
|
|
5141
|
+
}
|
|
5142
|
+
async function withSpinner(label, task) {
|
|
5143
|
+
if (!process.stdout.isTTY) {
|
|
5144
|
+
printStage("RUN", "RUN", label);
|
|
5145
|
+
return task;
|
|
5146
|
+
}
|
|
5147
|
+
const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
5148
|
+
let index = 0;
|
|
5149
|
+
process.stdout.write(`${paint(frames[index], "yellow")} ${label}`);
|
|
5150
|
+
const interval = setInterval(() => {
|
|
5151
|
+
index = (index + 1) % frames.length;
|
|
5152
|
+
process.stdout.write(`\r${paint(frames[index], "yellow")} ${label}`);
|
|
5153
|
+
}, 90);
|
|
5154
|
+
try {
|
|
5155
|
+
const result = await task;
|
|
5156
|
+
clearInterval(interval);
|
|
5157
|
+
process.stdout.write(`\r${paint("\u2713", "green")} ${label}
|
|
5158
|
+
`);
|
|
5159
|
+
return result;
|
|
5160
|
+
} catch (error) {
|
|
5161
|
+
clearInterval(interval);
|
|
5162
|
+
process.stdout.write(`\r${paint("\xD7", "red")} ${label}
|
|
5163
|
+
`);
|
|
5164
|
+
throw error;
|
|
5165
|
+
}
|
|
5166
|
+
}
|
|
5167
|
+
function previewRecord(dataset) {
|
|
5168
|
+
const file = dataset.files.find((item) => item.format === "jsonl" || item.format === "instruction" || item.format === "rag");
|
|
5169
|
+
const firstLine = file?.content.split(/\r?\n/).find((line) => line.trim().length > 0);
|
|
5170
|
+
if (!firstLine) return null;
|
|
5171
|
+
try {
|
|
5172
|
+
const parsed = JSON.parse(firstLine);
|
|
5173
|
+
const input = typeof parsed.input === "string" ? parsed.input : typeof parsed.instruction === "string" ? parsed.instruction : typeof parsed.question === "string" ? parsed.question : "";
|
|
5174
|
+
const output = typeof parsed.output === "string" ? parsed.output : typeof parsed.answer === "string" ? parsed.answer : typeof parsed.completion === "string" ? parsed.completion : typeof parsed.text === "string" ? parsed.text : "";
|
|
5175
|
+
if (!input && !output) return null;
|
|
5176
|
+
const metadata = parsed.metadata && typeof parsed.metadata === "object" ? parsed.metadata : {};
|
|
5177
|
+
const explanation = Array.isArray(metadata.acceptance_explanation) ? metadata.acceptance_explanation.filter((item) => typeof item === "string") : Array.isArray(metadata.acceptance_reasons) ? metadata.acceptance_reasons.filter((item) => typeof item === "string") : [];
|
|
5178
|
+
return { input: truncate(input, 92), output: truncate(output, 120), why: explanation.slice(0, 2).map((item) => truncate(item, 112)) };
|
|
5179
|
+
} catch {
|
|
5180
|
+
return null;
|
|
5181
|
+
}
|
|
5182
|
+
}
|
|
5088
5183
|
function depthMultiplier(depth) {
|
|
5089
5184
|
if (depth === "deep") return 1.6;
|
|
5090
5185
|
if (depth === "shallow") return 0.75;
|
|
5091
5186
|
return 1;
|
|
5092
5187
|
}
|
|
5093
5188
|
function printUsage(profile) {
|
|
5094
|
-
const name = profile.user.name ||
|
|
5095
|
-
|
|
5189
|
+
const name = profile.user.name || "Alys user";
|
|
5190
|
+
const email = profile.user.email;
|
|
5191
|
+
const account = email && email !== name ? `${name} <${email}>` : name;
|
|
5192
|
+
console.log(paint(`Account: ${account}`, "white"));
|
|
5096
5193
|
console.log(
|
|
5097
5194
|
profile.usage.isUnlimited ? paint("Generations: unlimited", "green") : paint(`Generations: ${profile.usage.used}/${profile.usage.limit} used, ${profile.usage.remaining} remaining`, "yellow")
|
|
5098
5195
|
);
|
|
@@ -5102,10 +5199,14 @@ function printRunPlan(args) {
|
|
|
5102
5199
|
const effectiveSources = Math.max(1, Math.floor(args.sourceLimit * multiplier));
|
|
5103
5200
|
const effectiveRows = Math.max(1, Math.floor(args.targetRows * multiplier));
|
|
5104
5201
|
const totalRows = effectiveRows * args.datasetCount;
|
|
5105
|
-
|
|
5202
|
+
const name = args.profile.user.name || "Alys user";
|
|
5203
|
+
const email = args.profile.user.email;
|
|
5204
|
+
const account = email && email !== name ? `${name} <${email}>` : name;
|
|
5205
|
+
console.log(paint("\n\u250C\u2500 Alys run plan \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510", "gray"));
|
|
5106
5206
|
console.log(`${paint("\u2502", "gray")} Topic ${paint(args.topic.slice(0, 58), "white")}`);
|
|
5107
|
-
console.log(`${paint("\u2502", "gray")}
|
|
5108
|
-
console.log(`${paint("\u2502", "gray")}
|
|
5207
|
+
console.log(`${paint("\u2502", "gray")} Account ${paint(account.slice(0, 58), "white")}`);
|
|
5208
|
+
console.log(`${paint("\u2502", "gray")} Type ${paint(args.datasetType, "cyan")} Depth ${paint(args.depth, "cyan")} Mode ${paint("Alys runtime", "yellow")}`);
|
|
5209
|
+
console.log(`${paint("\u2502", "gray")} Datasets ${formatInt(args.datasetCount)} / ${MAX_DATASETS_PER_RUN} max Rows/dataset ${formatInt(effectiveRows)} max`);
|
|
5109
5210
|
console.log(`${paint("\u2502", "gray")} Total rows ${paint(formatInt(totalRows), "green")} Formats ${args.exportFormats.join(", ")}`);
|
|
5110
5211
|
console.log(`${paint("\u2502", "gray")} Credits ${args.profile.usage.isUnlimited ? "Unlimited" : `${args.profile.usage.remaining ?? 0} remaining before run`}`);
|
|
5111
5212
|
console.log(`${paint("\u2502", "gray")} Output ${resolveHome(args.workspaceRoot)}`);
|
|
@@ -5121,7 +5222,7 @@ async function confirmRun(args) {
|
|
|
5121
5222
|
const response = await (0, import_prompts.default)({
|
|
5122
5223
|
type: "toggle",
|
|
5123
5224
|
name: "continueRun",
|
|
5124
|
-
message: "
|
|
5225
|
+
message: "Start this Alys run?",
|
|
5125
5226
|
initial: true,
|
|
5126
5227
|
active: "Yes",
|
|
5127
5228
|
inactive: "No"
|
|
@@ -5144,6 +5245,108 @@ async function writeGeneratedDatasets(workspaceRoot, datasets) {
|
|
|
5144
5245
|
);
|
|
5145
5246
|
}
|
|
5146
5247
|
}
|
|
5248
|
+
function printGenerationSummary(response, workspaceRoot) {
|
|
5249
|
+
const root = resolveHome(workspaceRoot);
|
|
5250
|
+
const totals = response.datasets.reduce(
|
|
5251
|
+
(acc, dataset) => {
|
|
5252
|
+
const metrics = getMetrics(dataset);
|
|
5253
|
+
const summary = getSummary(dataset);
|
|
5254
|
+
acc.records += Number(metrics.recordsGenerated ?? summary.recordsAccepted ?? 0);
|
|
5255
|
+
acc.sources += Number(metrics.sourcesDiscovered ?? 0);
|
|
5256
|
+
acc.documents += Number(metrics.documentsExtracted ?? 0);
|
|
5257
|
+
acc.findings += Number(metrics.findingsVerified ?? 0);
|
|
5258
|
+
acc.duplicates += Number(metrics.duplicatesRemoved ?? summary.duplicatesRemoved ?? 0);
|
|
5259
|
+
const quality = getQualityMetrics(dataset);
|
|
5260
|
+
acc.contradictions += Number(quality.contradictionResolutionCount ?? 0);
|
|
5261
|
+
acc.lowTrustFiltered += Number(quality.lowTrustSourceFilterRate ?? 0);
|
|
5262
|
+
acc.citationCoverage.push(Number(quality.citationCoverage ?? 0));
|
|
5263
|
+
acc.uniqueness.push(Number(quality.recordUniqueness ?? 0));
|
|
5264
|
+
acc.relevance.push(Number(quality.relevanceScore ?? 0));
|
|
5265
|
+
const suitability = getEvaluation(dataset).suitability ?? getEvaluation(dataset).summary?.scores ?? {};
|
|
5266
|
+
acc.ragSuitability.push(Number(suitability.ragSuitability ?? 0));
|
|
5267
|
+
acc.instructionTuning.push(Number(suitability.instructionTuning ?? 0));
|
|
5268
|
+
acc.factualGrounding.push(Number(suitability.factualGrounding ?? 0));
|
|
5269
|
+
acc.humanUsefulness.push(Number(suitability.humanUsefulness ?? 0));
|
|
5270
|
+
const confidence2 = Number(metrics.averageConfidence ?? summary.averageConfidence ?? 0);
|
|
5271
|
+
if (confidence2 > 0) acc.confidences.push(confidence2);
|
|
5272
|
+
return acc;
|
|
5273
|
+
},
|
|
5274
|
+
{
|
|
5275
|
+
records: 0,
|
|
5276
|
+
sources: 0,
|
|
5277
|
+
documents: 0,
|
|
5278
|
+
findings: 0,
|
|
5279
|
+
duplicates: 0,
|
|
5280
|
+
contradictions: 0,
|
|
5281
|
+
lowTrustFiltered: 0,
|
|
5282
|
+
confidences: [],
|
|
5283
|
+
citationCoverage: [],
|
|
5284
|
+
uniqueness: [],
|
|
5285
|
+
relevance: [],
|
|
5286
|
+
ragSuitability: [],
|
|
5287
|
+
instructionTuning: [],
|
|
5288
|
+
factualGrounding: [],
|
|
5289
|
+
humanUsefulness: []
|
|
5290
|
+
}
|
|
5291
|
+
);
|
|
5292
|
+
const confidence = totals.confidences.length ? totals.confidences.reduce((sum, value) => sum + value, 0) / totals.confidences.length : 0;
|
|
5293
|
+
const citationCoverage = average(totals.citationCoverage);
|
|
5294
|
+
const uniqueness = average(totals.uniqueness);
|
|
5295
|
+
const relevance = average(totals.relevance);
|
|
5296
|
+
const ragSuitability = average(totals.ragSuitability);
|
|
5297
|
+
const instructionTuning = average(totals.instructionTuning);
|
|
5298
|
+
const factualGrounding = average(totals.factualGrounding);
|
|
5299
|
+
const humanUsefulness = average(totals.humanUsefulness);
|
|
5300
|
+
console.log("");
|
|
5301
|
+
console.log(paint("Alys run complete", "green"));
|
|
5302
|
+
printStage("SRC", "DONE", "Authoritative sources ranked", formatInt(totals.sources));
|
|
5303
|
+
printStage("SRC", "DONE", "Low-trust source filter applied", `${Math.round(totals.lowTrustFiltered / Math.max(1, response.datasets.length) * 100)}% avg filtered`);
|
|
5304
|
+
printStage("EXT", "DONE", "Source documents normalized", formatInt(totals.documents));
|
|
5305
|
+
printStage("CHK", "DONE", "Findings verified", formatInt(totals.findings));
|
|
5306
|
+
printStage("CHK", "DONE", "Contradictory claims resolved", formatInt(totals.contradictions));
|
|
5307
|
+
printStage("DED", "DONE", "Duplicate candidates removed", formatInt(totals.duplicates));
|
|
5308
|
+
printStage("GEN", "DONE", "Canonical records accepted", formatInt(totals.records));
|
|
5309
|
+
printStage("EVAL", "DONE", "Average confidence", formatPercent(confidence));
|
|
5310
|
+
printStage("EVAL", "DONE", "Citation coverage", formatPercent(citationCoverage));
|
|
5311
|
+
printStage("EVAL", "DONE", "Record uniqueness", formatPercent(uniqueness));
|
|
5312
|
+
printStage("EVAL", "DONE", "Topic relevance", formatPercent(relevance));
|
|
5313
|
+
printStage("EVAL", "DONE", "RAG suitability", formatScore(ragSuitability));
|
|
5314
|
+
printStage("EVAL", "DONE", "Instruction tuning suitability", formatScore(instructionTuning));
|
|
5315
|
+
printStage("EVAL", "DONE", "Factual grounding", formatScore(factualGrounding));
|
|
5316
|
+
printStage("EVAL", "DONE", "Human usefulness proxy", formatScore(humanUsefulness));
|
|
5317
|
+
printStage("OUT", "DONE", "Exports written", root);
|
|
5318
|
+
console.log("");
|
|
5319
|
+
console.log(paint("Datasets", "white"));
|
|
5320
|
+
for (const dataset of response.datasets) {
|
|
5321
|
+
const metrics = getMetrics(dataset);
|
|
5322
|
+
const summary = getSummary(dataset);
|
|
5323
|
+
const quality = getQualityMetrics(dataset);
|
|
5324
|
+
const suitability = getEvaluation(dataset).suitability ?? getEvaluation(dataset).summary?.scores ?? {};
|
|
5325
|
+
const records = Number(metrics.recordsGenerated ?? summary.recordsAccepted ?? 0);
|
|
5326
|
+
const sources = Number(metrics.sourcesDiscovered ?? 0);
|
|
5327
|
+
const confidenceValue = Number(metrics.averageConfidence ?? summary.averageConfidence ?? 0);
|
|
5328
|
+
const outputDir = import_node_path.default.join(root, "datasets", dataset.id);
|
|
5329
|
+
console.log(`${paint("\u2022", "yellow")} ${paint(dataset.id, "white")} ${formatInt(records)} records ${formatInt(sources)} sources ${formatPercent(confidenceValue)} confidence`);
|
|
5330
|
+
console.log(` ${truncate(dataset.topic, 110)}`);
|
|
5331
|
+
console.log(` ${paint(outputDir, "cyan")}`);
|
|
5332
|
+
console.log(` quality ${formatPercent(Number(quality.citationCoverage ?? 0))} citations \xB7 ${formatPercent(Number(quality.recordUniqueness ?? 0))} unique \xB7 ${formatPercent(Number(quality.sourceDiversity ?? 0))} source diversity`);
|
|
5333
|
+
console.log(` suitability RAG ${formatScore(Number(suitability.ragSuitability ?? 0))} \xB7 tuning ${formatScore(Number(suitability.instructionTuning ?? 0))} \xB7 usefulness ${formatScore(Number(suitability.humanUsefulness ?? 0))}`);
|
|
5334
|
+
const preview = previewRecord(dataset);
|
|
5335
|
+
if (preview) {
|
|
5336
|
+
console.log(paint(" preview", "gray"));
|
|
5337
|
+
if (preview.input) console.log(` in ${paint(preview.input, "gray")}`);
|
|
5338
|
+
if (preview.output) console.log(` out ${preview.output}`);
|
|
5339
|
+
for (const reason of preview.why) {
|
|
5340
|
+
console.log(` why ${paint(reason, "gray")}`);
|
|
5341
|
+
}
|
|
5342
|
+
}
|
|
5343
|
+
}
|
|
5344
|
+
console.log("");
|
|
5345
|
+
console.log(
|
|
5346
|
+
response.usage.isUnlimited ? paint("Generations remaining: unlimited", "green") : paint(`Generations remaining: ${response.usage.remaining ?? 0}`, "yellow")
|
|
5347
|
+
);
|
|
5348
|
+
console.log(paint(`Dashboard: ${appUrl()}/dashboard`, "cyan"));
|
|
5349
|
+
}
|
|
5147
5350
|
async function handleStatus() {
|
|
5148
5351
|
printBanner();
|
|
5149
5352
|
const { profile } = await ensureAuthenticated();
|
|
@@ -5171,6 +5374,9 @@ async function handleLogout() {
|
|
|
5171
5374
|
}
|
|
5172
5375
|
async function handleGenerate(args, command) {
|
|
5173
5376
|
const { config, profile } = await ensureAuthenticated();
|
|
5377
|
+
printBanner();
|
|
5378
|
+
printUsage(profile);
|
|
5379
|
+
console.log("");
|
|
5174
5380
|
const { values, positionals } = (0, import_node_util.parseArgs)({
|
|
5175
5381
|
args: command === "generate" ? args.slice(1) : args,
|
|
5176
5382
|
allowPositionals: true,
|
|
@@ -5187,13 +5393,13 @@ async function handleGenerate(args, command) {
|
|
|
5187
5393
|
yes: { type: "boolean" }
|
|
5188
5394
|
}
|
|
5189
5395
|
});
|
|
5190
|
-
const topicFromArgs = positionals.join(" ")
|
|
5191
|
-
const topic = topicFromArgs ? topicFromArgs : (await (0, import_prompts.default)({
|
|
5396
|
+
const topicFromArgs = normalizeTopicInput(positionals.join(" "));
|
|
5397
|
+
const topic = topicFromArgs ? topicFromArgs : normalizeTopicInput((await (0, import_prompts.default)({
|
|
5192
5398
|
type: "text",
|
|
5193
5399
|
name: "topic",
|
|
5194
5400
|
message: "What do you want to generate?",
|
|
5195
5401
|
validate: (v) => v.trim().length ? true : "Please enter a topic."
|
|
5196
|
-
})).topic;
|
|
5402
|
+
})).topic);
|
|
5197
5403
|
if (!topic) throw new Error("Missing topic.");
|
|
5198
5404
|
const datasetType = parseDatasetType(values.type) ?? (await (0, import_prompts.default)({
|
|
5199
5405
|
type: "select",
|
|
@@ -5241,19 +5447,21 @@ async function handleGenerate(args, command) {
|
|
|
5241
5447
|
{ title: "Deep", value: "deep" }
|
|
5242
5448
|
]
|
|
5243
5449
|
})).depth;
|
|
5244
|
-
const sourceLimit = values.sources ? Math.max(1, Number(values.sources)) : (await (0, import_prompts.default)({
|
|
5450
|
+
const sourceLimit = values.sources ? Math.min(MAX_SOURCES_PER_RUN, Math.max(1, Number(values.sources))) : (await (0, import_prompts.default)({
|
|
5245
5451
|
type: "number",
|
|
5246
5452
|
name: "sourceLimit",
|
|
5247
5453
|
message: "How many sources?",
|
|
5248
|
-
initial:
|
|
5249
|
-
min: 1
|
|
5454
|
+
initial: MAX_SOURCES_PER_RUN,
|
|
5455
|
+
min: 1,
|
|
5456
|
+
max: MAX_SOURCES_PER_RUN
|
|
5250
5457
|
})).sourceLimit;
|
|
5251
|
-
const targetRows = values.rows ? Math.max(1, Number(values.rows)) : (await (0, import_prompts.default)({
|
|
5458
|
+
const targetRows = values.rows ? Math.min(MAX_ROWS_PER_DATASET, Math.max(1, Number(values.rows))) : (await (0, import_prompts.default)({
|
|
5252
5459
|
type: "number",
|
|
5253
5460
|
name: "targetRows",
|
|
5254
5461
|
message: "Rows per dataset?",
|
|
5255
|
-
initial:
|
|
5256
|
-
min: 1
|
|
5462
|
+
initial: MAX_ROWS_PER_DATASET,
|
|
5463
|
+
min: 1,
|
|
5464
|
+
max: MAX_ROWS_PER_DATASET
|
|
5257
5465
|
})).targetRows;
|
|
5258
5466
|
const workspaceRoot = (values.workspace ? String(values.workspace) : "").trim() || (await (0, import_prompts.default)({
|
|
5259
5467
|
type: "text",
|
|
@@ -5265,13 +5473,11 @@ async function handleGenerate(args, command) {
|
|
|
5265
5473
|
const verificationEnabled = values.verify === true ? true : values["no-verify"] === true ? false : (await (0, import_prompts.default)({
|
|
5266
5474
|
type: "toggle",
|
|
5267
5475
|
name: "verificationEnabled",
|
|
5268
|
-
message: "Enable verification
|
|
5476
|
+
message: "Enable verification checks?",
|
|
5269
5477
|
initial: true,
|
|
5270
5478
|
active: "Yes",
|
|
5271
5479
|
inactive: "No"
|
|
5272
5480
|
})).verificationEnabled;
|
|
5273
|
-
printBanner();
|
|
5274
|
-
printUsage(profile);
|
|
5275
5481
|
printRunPlan({
|
|
5276
5482
|
topic,
|
|
5277
5483
|
datasetType,
|
|
@@ -5292,39 +5498,32 @@ async function handleGenerate(args, command) {
|
|
|
5292
5498
|
console.log(paint("Run cancelled. No generations spent.", "green"));
|
|
5293
5499
|
return;
|
|
5294
5500
|
}
|
|
5295
|
-
console.log(
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
for (const dataset of response.datasets) {
|
|
5319
|
-
const records = Number(dataset.manifest?.metrics && typeof dataset.manifest.metrics === "object" ? dataset.manifest.metrics.recordsGenerated ?? 0 : 0);
|
|
5320
|
-
console.log(`${paint("\u2022", "yellow")} ${dataset.id} records: ${formatInt(records)}`);
|
|
5321
|
-
console.log(` ${import_node_path.default.join(resolveHome(workspaceRoot), "datasets", dataset.id)}`);
|
|
5322
|
-
}
|
|
5323
|
-
console.log("");
|
|
5324
|
-
console.log(
|
|
5325
|
-
response.usage.isUnlimited ? paint("Generations remaining: unlimited", "green") : paint(`Generations remaining: ${response.usage.remaining ?? 0}`, "yellow")
|
|
5501
|
+
console.log(paint("Runtime", "white"));
|
|
5502
|
+
printStage("AUTH", "OK", "Usage linked", appUrl());
|
|
5503
|
+
printStage("PLAN", "OK", "Generations charged only after successful completion", `${datasetCount} requested`);
|
|
5504
|
+
printStage("SRC", "RUN", "Research pipeline starting", `${sourceLimit} source target`);
|
|
5505
|
+
const response = await withSpinner(
|
|
5506
|
+
"Alys research runtime executing",
|
|
5507
|
+
requestJson(
|
|
5508
|
+
"/api/cli/generate",
|
|
5509
|
+
{
|
|
5510
|
+
method: "POST",
|
|
5511
|
+
body: JSON.stringify({
|
|
5512
|
+
topic,
|
|
5513
|
+
datasetType,
|
|
5514
|
+
datasetCount,
|
|
5515
|
+
formats: exportFormats,
|
|
5516
|
+
sourceLimit,
|
|
5517
|
+
targetRows,
|
|
5518
|
+
depth,
|
|
5519
|
+
verificationEnabled
|
|
5520
|
+
})
|
|
5521
|
+
},
|
|
5522
|
+
config.token
|
|
5523
|
+
)
|
|
5326
5524
|
);
|
|
5327
|
-
|
|
5525
|
+
await withSpinner("Writing local exports", writeGeneratedDatasets(workspaceRoot, response.datasets));
|
|
5526
|
+
printGenerationSummary(response, workspaceRoot);
|
|
5328
5527
|
}
|
|
5329
5528
|
function printFailure(error) {
|
|
5330
5529
|
const message = error instanceof Error ? error.message : "Alys failed.";
|