lua-cli 3.16.2 → 3.17.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/dist/api-exports.d.ts +28 -0
- package/dist/api-exports.js +2 -1
- package/dist/api-exports.js.map +1 -1
- package/dist/index.js +1307 -210
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/template/lua.skill.yaml +7 -0
- package/template/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -132,13 +132,14 @@ var init_semver = __esm({
|
|
|
132
132
|
// src/config/constants.ts
|
|
133
133
|
import { join } from "path";
|
|
134
134
|
import { homedir } from "os";
|
|
135
|
-
var CLI_CONFIG_DIR, VERSION_CHECK_FILE, TELEMETRY_FILE, BASE_URLS, CREDENTIALS_FILE, PREFERRED_AGENT_TYPES, SANDBOX_STORAGE_FILE, POSTHOG_API_KEY, POSTHOG_HOST;
|
|
135
|
+
var CLI_CONFIG_DIR, VERSION_CHECK_FILE, TELEMETRY_FILE, CLI_CACHE_FILE, BASE_URLS, CREDENTIALS_FILE, PREFERRED_AGENT_TYPES, SANDBOX_STORAGE_FILE, POSTHOG_API_KEY, POSTHOG_HOST;
|
|
136
136
|
var init_constants = __esm({
|
|
137
137
|
"src/config/constants.ts"() {
|
|
138
138
|
"use strict";
|
|
139
139
|
CLI_CONFIG_DIR = join(homedir(), ".lua-cli");
|
|
140
140
|
VERSION_CHECK_FILE = join(CLI_CONFIG_DIR, "version-check.json");
|
|
141
141
|
TELEMETRY_FILE = join(CLI_CONFIG_DIR, "telemetry.json");
|
|
142
|
+
CLI_CACHE_FILE = join(CLI_CONFIG_DIR, "cache.json");
|
|
142
143
|
BASE_URLS = {
|
|
143
144
|
API: process.env.LUA_API_URL || "https://api.heylua.ai",
|
|
144
145
|
AUTH: process.env.LUA_AUTH_URL || "https://auth.heylua.ai",
|
|
@@ -1526,7 +1527,7 @@ var init_artifact_loader = __esm({
|
|
|
1526
1527
|
});
|
|
1527
1528
|
|
|
1528
1529
|
// src/api/backup.api.service.ts
|
|
1529
|
-
var BackupApi;
|
|
1530
|
+
var BackupApi, backup_api_service_default;
|
|
1530
1531
|
var init_backup_api_service = __esm({
|
|
1531
1532
|
"src/api/backup.api.service.ts"() {
|
|
1532
1533
|
"use strict";
|
|
@@ -1645,7 +1646,20 @@ var init_backup_api_service = __esm({
|
|
|
1645
1646
|
Authorization: `Bearer ${this.apiKey}`
|
|
1646
1647
|
});
|
|
1647
1648
|
}
|
|
1649
|
+
/**
|
|
1650
|
+
* Get the list of backup versions for this agent.
|
|
1651
|
+
*
|
|
1652
|
+
* @param all - If true, lifts the server-side 50-version cap
|
|
1653
|
+
* @returns Promise resolving to the list of version summaries (newest first)
|
|
1654
|
+
*/
|
|
1655
|
+
async getBackupVersions(all = false) {
|
|
1656
|
+
const qs = all ? "?all=true" : "";
|
|
1657
|
+
return this.httpGet(`/developer/agents/${this.agentId}/backup/versions${qs}`, {
|
|
1658
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
1659
|
+
});
|
|
1660
|
+
}
|
|
1648
1661
|
};
|
|
1662
|
+
backup_api_service_default = BackupApi;
|
|
1649
1663
|
}
|
|
1650
1664
|
});
|
|
1651
1665
|
|
|
@@ -1662,7 +1676,7 @@ async function ensureBundlesUploaded(apiKey, agentId, bundles) {
|
|
|
1662
1676
|
uploaded: 0
|
|
1663
1677
|
};
|
|
1664
1678
|
}
|
|
1665
|
-
const api = new
|
|
1679
|
+
const api = new backup_api_service_default(BASE_URLS.API, apiKey, agentId);
|
|
1666
1680
|
const hashes = Array.from(bundles.keys());
|
|
1667
1681
|
const urlResponse = await api.getBlobUploadUrls(hashes);
|
|
1668
1682
|
if (!urlResponse.success) {
|
|
@@ -5053,11 +5067,11 @@ var init_mcp_server_plugin = __esm({
|
|
|
5053
5067
|
// ../shared-source-sync/dist/index.mjs
|
|
5054
5068
|
import { createHash } from "crypto";
|
|
5055
5069
|
import { extname } from "path";
|
|
5056
|
-
import { readdirSync as readdirSync2, readFileSync as
|
|
5070
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync7, statSync as statSync2 } from "fs";
|
|
5057
5071
|
import { join as join4, sep } from "path";
|
|
5058
5072
|
import { gunzipSync, gzipSync } from "zlib";
|
|
5059
|
-
import { existsSync as existsSync5, mkdirSync as
|
|
5060
|
-
import { dirname as
|
|
5073
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync6, readFileSync as readFileSync22, statSync as statSync22, writeFileSync as writeFileSync6 } from "fs";
|
|
5074
|
+
import { dirname as dirname4, join as join22, resolve, sep as sep2 } from "path";
|
|
5061
5075
|
import { mkdirSync as mkdirSync22, readdirSync as readdirSync22, readFileSync as readFileSync32, statSync as statSync3, writeFileSync as writeFileSync22 } from "fs";
|
|
5062
5076
|
import { dirname as dirname22, join as join32, sep as sep3 } from "path";
|
|
5063
5077
|
import { gunzipSync as gunzipSync2, gzipSync as gzipSync2 } from "zlib";
|
|
@@ -5117,7 +5131,7 @@ function walkWorkspace(rootDir, opts = {}) {
|
|
|
5117
5131
|
if (stats.size > maxBytes) continue;
|
|
5118
5132
|
let content;
|
|
5119
5133
|
try {
|
|
5120
|
-
content =
|
|
5134
|
+
content = readFileSync7(abs);
|
|
5121
5135
|
} catch {
|
|
5122
5136
|
continue;
|
|
5123
5137
|
}
|
|
@@ -5234,10 +5248,10 @@ function restoreFromBlobs(manifest, blobs, targetDir, opts = {}) {
|
|
|
5234
5248
|
continue;
|
|
5235
5249
|
}
|
|
5236
5250
|
}
|
|
5237
|
-
|
|
5251
|
+
mkdirSync6(dirname4(targetPath), {
|
|
5238
5252
|
recursive: true
|
|
5239
5253
|
});
|
|
5240
|
-
|
|
5254
|
+
writeFileSync6(targetPath, content);
|
|
5241
5255
|
filesWritten++;
|
|
5242
5256
|
}
|
|
5243
5257
|
return {
|
|
@@ -5432,12 +5446,12 @@ var init_dist2 = __esm({
|
|
|
5432
5446
|
this.options = options;
|
|
5433
5447
|
this.fetchFn = options.fetch ?? fetch;
|
|
5434
5448
|
}
|
|
5435
|
-
url(
|
|
5449
|
+
url(path19) {
|
|
5436
5450
|
const base = this.options.baseUrl.replace(/\/$/, "");
|
|
5437
|
-
return `${base}/developer/agents/${encodeURIComponent(this.options.agentId)}${
|
|
5451
|
+
return `${base}/developer/agents/${encodeURIComponent(this.options.agentId)}${path19}`;
|
|
5438
5452
|
}
|
|
5439
|
-
async json(method,
|
|
5440
|
-
const endpoint = this.url(
|
|
5453
|
+
async json(method, path19, body) {
|
|
5454
|
+
const endpoint = this.url(path19);
|
|
5441
5455
|
const res = await this.fetchFn(endpoint, {
|
|
5442
5456
|
method,
|
|
5443
5457
|
headers: {
|
|
@@ -5456,7 +5470,7 @@ var init_dist2 = __esm({
|
|
|
5456
5470
|
} catch {
|
|
5457
5471
|
text2 = void 0;
|
|
5458
5472
|
}
|
|
5459
|
-
throw new BackupHttpError(`Backup request failed: ${method} ${
|
|
5473
|
+
throw new BackupHttpError(`Backup request failed: ${method} ${path19} \u2192 ${res.status} ${res.statusText}`, res.status, endpoint, text2);
|
|
5460
5474
|
}
|
|
5461
5475
|
const text = await res.text();
|
|
5462
5476
|
if (!text) return void 0;
|
|
@@ -5523,16 +5537,16 @@ var init_dist2 = __esm({
|
|
|
5523
5537
|
});
|
|
5524
5538
|
|
|
5525
5539
|
// src/compiler/utils/common.ts
|
|
5526
|
-
import
|
|
5540
|
+
import path4 from "path";
|
|
5527
5541
|
function hashContent(content) {
|
|
5528
5542
|
return hashContentTruncated(content);
|
|
5529
5543
|
}
|
|
5530
5544
|
function isInside(child, parent) {
|
|
5531
|
-
const resolvedChild =
|
|
5532
|
-
const resolvedParent =
|
|
5545
|
+
const resolvedChild = path4.resolve(child);
|
|
5546
|
+
const resolvedParent = path4.resolve(parent);
|
|
5533
5547
|
if (resolvedChild === resolvedParent) return true;
|
|
5534
|
-
const rel =
|
|
5535
|
-
return !!rel && !rel.startsWith("..") && !
|
|
5548
|
+
const rel = path4.relative(resolvedParent, resolvedChild);
|
|
5549
|
+
return !!rel && !rel.startsWith("..") && !path4.isAbsolute(rel);
|
|
5536
5550
|
}
|
|
5537
5551
|
function classifyProjectFile(name) {
|
|
5538
5552
|
if (name.endsWith(".ts") || name.endsWith(".tsx") || name.endsWith(".js")) {
|
|
@@ -5561,20 +5575,20 @@ var init_common = __esm({
|
|
|
5561
5575
|
});
|
|
5562
5576
|
|
|
5563
5577
|
// src/compiler/utils/path-resolver.ts
|
|
5564
|
-
import * as
|
|
5565
|
-
import * as
|
|
5578
|
+
import * as fs4 from "fs";
|
|
5579
|
+
import * as path5 from "path";
|
|
5566
5580
|
function getTsConfigPathMappings(rootDir) {
|
|
5567
|
-
const resolvedRoot =
|
|
5581
|
+
const resolvedRoot = path5.resolve(rootDir);
|
|
5568
5582
|
if (mappingsCache.has(resolvedRoot)) {
|
|
5569
5583
|
return mappingsCache.get(resolvedRoot) ?? null;
|
|
5570
5584
|
}
|
|
5571
|
-
const tsconfigPath =
|
|
5572
|
-
if (!
|
|
5585
|
+
const tsconfigPath = path5.join(resolvedRoot, "tsconfig.json");
|
|
5586
|
+
if (!fs4.existsSync(tsconfigPath)) {
|
|
5573
5587
|
mappingsCache.set(resolvedRoot, null);
|
|
5574
5588
|
return null;
|
|
5575
5589
|
}
|
|
5576
5590
|
try {
|
|
5577
|
-
const tsconfigContent =
|
|
5591
|
+
const tsconfigContent = fs4.readFileSync(tsconfigPath, "utf-8");
|
|
5578
5592
|
const tsconfig = JSON.parse(tsconfigContent);
|
|
5579
5593
|
const compilerOptions = tsconfig.compilerOptions || {};
|
|
5580
5594
|
if (compilerOptions.paths) {
|
|
@@ -5601,7 +5615,7 @@ function resolvePathAlias(specifier, rootDir) {
|
|
|
5601
5615
|
if (match) {
|
|
5602
5616
|
const captured = match[1] || "";
|
|
5603
5617
|
const targetPath = targets[0].replace("*", captured);
|
|
5604
|
-
return
|
|
5618
|
+
return path5.join(mappings.rootDir, mappings.baseUrl, targetPath);
|
|
5605
5619
|
}
|
|
5606
5620
|
}
|
|
5607
5621
|
return null;
|
|
@@ -5613,20 +5627,20 @@ function resolveModuleSpecifier(specifier, fromFile, rootDir) {
|
|
|
5613
5627
|
return tryExtensions(aliasResolved);
|
|
5614
5628
|
}
|
|
5615
5629
|
if (normalized.startsWith("./") || normalized.startsWith("../")) {
|
|
5616
|
-
const basePath =
|
|
5630
|
+
const basePath = path5.resolve(path5.dirname(fromFile), normalized);
|
|
5617
5631
|
return tryExtensions(basePath);
|
|
5618
5632
|
}
|
|
5619
5633
|
return void 0;
|
|
5620
5634
|
}
|
|
5621
5635
|
function tryExtensions(basePath) {
|
|
5622
5636
|
for (const ext of MODULE_EXTENSIONS) {
|
|
5623
|
-
const full = ext.startsWith("/") ?
|
|
5624
|
-
if (
|
|
5637
|
+
const full = ext.startsWith("/") ? path5.join(basePath, ext) : basePath + ext;
|
|
5638
|
+
if (fs4.existsSync(full)) return full;
|
|
5625
5639
|
}
|
|
5626
5640
|
return void 0;
|
|
5627
5641
|
}
|
|
5628
5642
|
function registerProjectRootDir(project, rootDir) {
|
|
5629
|
-
projectRootDirs.set(project,
|
|
5643
|
+
projectRootDirs.set(project, path5.resolve(rootDir));
|
|
5630
5644
|
}
|
|
5631
5645
|
function getProjectRootDir(project) {
|
|
5632
5646
|
return projectRootDirs.get(project);
|
|
@@ -6226,7 +6240,7 @@ var init_reference_resolver = __esm({
|
|
|
6226
6240
|
});
|
|
6227
6241
|
|
|
6228
6242
|
// src/compiler/plugins/skill.plugin.ts
|
|
6229
|
-
import
|
|
6243
|
+
import fs5 from "fs/promises";
|
|
6230
6244
|
import { Node as Node11 } from "ts-morph";
|
|
6231
6245
|
function findEnclosingVariableDeclaration(config) {
|
|
6232
6246
|
let current = config.getParent();
|
|
@@ -6559,7 +6573,7 @@ var init_skill_plugin = __esm({
|
|
|
6559
6573
|
description: metadata.description,
|
|
6560
6574
|
metadata: this.sanitizeForPersistence(metadata.metadata)
|
|
6561
6575
|
}, null, 2);
|
|
6562
|
-
const originalSource = await
|
|
6576
|
+
const originalSource = await fs5.readFile(metadata.sourcePath, "utf-8");
|
|
6563
6577
|
return {
|
|
6564
6578
|
code,
|
|
6565
6579
|
sourceMap: "",
|
|
@@ -7313,10 +7327,10 @@ var init_device_trigger_plugin = __esm({
|
|
|
7313
7327
|
});
|
|
7314
7328
|
|
|
7315
7329
|
// src/compiler/utils/primitive-rewrite.ts
|
|
7316
|
-
import { readFileSync as
|
|
7330
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
7317
7331
|
import { Node as Node14, Project, ts as ts3 } from "ts-morph";
|
|
7318
7332
|
function rewritePrimitiveSource(metadata, opts) {
|
|
7319
|
-
const sourceCode =
|
|
7333
|
+
const sourceCode = readFileSync9(metadata.sourcePath, "utf-8");
|
|
7320
7334
|
const localProject = new Project({
|
|
7321
7335
|
useInMemoryFileSystem: true,
|
|
7322
7336
|
compilerOptions: {
|
|
@@ -7655,7 +7669,7 @@ var init_cross_file_specs = __esm({
|
|
|
7655
7669
|
});
|
|
7656
7670
|
|
|
7657
7671
|
// src/compiler/plugins/voice.plugin.ts
|
|
7658
|
-
import
|
|
7672
|
+
import fs6 from "fs/promises";
|
|
7659
7673
|
import { Node as Node15 } from "ts-morph";
|
|
7660
7674
|
function astObjectToPlain(obj) {
|
|
7661
7675
|
const result = {};
|
|
@@ -8196,8 +8210,8 @@ var init_voice_plugin = __esm({
|
|
|
8196
8210
|
}, "isMissingTopLevelRequired");
|
|
8197
8211
|
for (const issue of parsed.error.issues) {
|
|
8198
8212
|
if (isMissingTopLevelRequired(issue)) continue;
|
|
8199
|
-
const
|
|
8200
|
-
errors.push(validationError(`Voice config invalid at \`${
|
|
8213
|
+
const path19 = issue.path.length > 0 ? issue.path.join(".") : "<root>";
|
|
8214
|
+
errors.push(validationError(`Voice config invalid at \`${path19}\`: ${issue.message}`, {
|
|
8201
8215
|
line
|
|
8202
8216
|
}));
|
|
8203
8217
|
}
|
|
@@ -8278,7 +8292,7 @@ var init_voice_plugin = __esm({
|
|
|
8278
8292
|
description: metadata.description,
|
|
8279
8293
|
metadata: sanitized
|
|
8280
8294
|
}, null, 2);
|
|
8281
|
-
const originalSource = await
|
|
8295
|
+
const originalSource = await fs6.readFile(metadata.sourcePath, "utf-8");
|
|
8282
8296
|
return {
|
|
8283
8297
|
code,
|
|
8284
8298
|
sourceMap: "",
|
|
@@ -8431,8 +8445,8 @@ var init_registry = __esm({
|
|
|
8431
8445
|
});
|
|
8432
8446
|
|
|
8433
8447
|
// src/compiler/bundler.ts
|
|
8434
|
-
import
|
|
8435
|
-
import
|
|
8448
|
+
import fs7 from "fs/promises";
|
|
8449
|
+
import path6 from "path";
|
|
8436
8450
|
import crypto4 from "crypto";
|
|
8437
8451
|
import { build } from "esbuild";
|
|
8438
8452
|
var Bundler;
|
|
@@ -8501,9 +8515,9 @@ var init_bundler = __esm({
|
|
|
8501
8515
|
* Bundle a primitive's entry point using esbuild.
|
|
8502
8516
|
*/
|
|
8503
8517
|
async bundle(metadata, entryPointCode) {
|
|
8504
|
-
const tempDir =
|
|
8505
|
-
const outfile =
|
|
8506
|
-
const sourceDir =
|
|
8518
|
+
const tempDir = path6.join(this.options.outDir, ".temp");
|
|
8519
|
+
const outfile = path6.join(tempDir, `${metadata.kind}-${metadata.name}.bundle.js`);
|
|
8520
|
+
const sourceDir = path6.dirname(metadata.sourcePath);
|
|
8507
8521
|
if (this.options.debug) {
|
|
8508
8522
|
this.verbose(` Source: ${metadata.sourcePath}`);
|
|
8509
8523
|
this.verbose(` Output: ${outfile}`);
|
|
@@ -8533,15 +8547,15 @@ var init_bundler = __esm({
|
|
|
8533
8547
|
],
|
|
8534
8548
|
logLevel: this.options.debug ? "debug" : "silent"
|
|
8535
8549
|
});
|
|
8536
|
-
const code = await
|
|
8550
|
+
const code = await fs7.readFile(outfile, "utf-8");
|
|
8537
8551
|
let sourceMap = "";
|
|
8538
8552
|
try {
|
|
8539
|
-
sourceMap = await
|
|
8553
|
+
sourceMap = await fs7.readFile(outfile + ".map", "utf-8");
|
|
8540
8554
|
} catch {
|
|
8541
8555
|
}
|
|
8542
|
-
const originalSource = await
|
|
8556
|
+
const originalSource = await fs7.readFile(metadata.sourcePath, "utf-8");
|
|
8543
8557
|
const hash = crypto4.createHash("sha256").update(code).digest("hex").slice(0, 16);
|
|
8544
|
-
const stats = await
|
|
8558
|
+
const stats = await fs7.stat(outfile);
|
|
8545
8559
|
return {
|
|
8546
8560
|
code,
|
|
8547
8561
|
sourceMap,
|
|
@@ -8558,14 +8572,14 @@ var init_bundler = __esm({
|
|
|
8558
8572
|
const bundler = this;
|
|
8559
8573
|
const sourcePath = metadata.sourcePath;
|
|
8560
8574
|
const exportName = metadata.exportName;
|
|
8561
|
-
const sourceDir =
|
|
8575
|
+
const sourceDir = path6.dirname(sourcePath);
|
|
8562
8576
|
return {
|
|
8563
8577
|
name: "lua-virtual-source",
|
|
8564
8578
|
setup(build2) {
|
|
8565
8579
|
build2.onResolve({
|
|
8566
8580
|
filter: /.*/
|
|
8567
8581
|
}, (args2) => {
|
|
8568
|
-
const resolved = args2.path.startsWith(".") ?
|
|
8582
|
+
const resolved = args2.path.startsWith(".") ? path6.resolve(args2.resolveDir, args2.path) : args2.path;
|
|
8569
8583
|
const normalizedResolved = resolved.replace(/\.(ts|tsx|js|jsx)$/, "");
|
|
8570
8584
|
const normalizedSource = sourcePath.replace(/\.(ts|tsx|js|jsx)$/, "");
|
|
8571
8585
|
if (normalizedResolved === normalizedSource) {
|
|
@@ -8581,8 +8595,8 @@ var init_bundler = __esm({
|
|
|
8581
8595
|
namespace: "lua-virtual-source"
|
|
8582
8596
|
}, async () => {
|
|
8583
8597
|
const sourceFile = bundler.project.getSourceFile(sourcePath);
|
|
8584
|
-
let content = sourceFile?.getText() ?? await
|
|
8585
|
-
content = bundler.stripLuaCliImportsAST(content,
|
|
8598
|
+
let content = sourceFile?.getText() ?? await fs7.readFile(sourcePath, "utf-8");
|
|
8599
|
+
content = bundler.stripLuaCliImportsAST(content, path6.basename(sourcePath));
|
|
8586
8600
|
const virtualContent = metadata.isDefaultExport ? content : `${content}
|
|
8587
8601
|
export { ${exportName} as __lua_target__ };
|
|
8588
8602
|
`;
|
|
@@ -8610,17 +8624,17 @@ export { ${exportName} as __lua_target__ };
|
|
|
8610
8624
|
namespace: "file"
|
|
8611
8625
|
}, async (args2) => {
|
|
8612
8626
|
if (args2.path.includes("node_modules")) return null;
|
|
8613
|
-
const contents = await
|
|
8627
|
+
const contents = await fs7.readFile(args2.path, "utf-8");
|
|
8614
8628
|
if (!contents.includes("lua-cli") && !contents.includes("api-exports")) {
|
|
8615
8629
|
return null;
|
|
8616
8630
|
}
|
|
8617
8631
|
try {
|
|
8618
|
-
const modifiedContents = stripImports(contents,
|
|
8632
|
+
const modifiedContents = stripImports(contents, path6.basename(args2.path));
|
|
8619
8633
|
if (modifiedContents !== contents) {
|
|
8620
8634
|
return {
|
|
8621
8635
|
contents: modifiedContents,
|
|
8622
8636
|
loader: args2.path.endsWith(".ts") || args2.path.endsWith(".tsx") ? "ts" : "js",
|
|
8623
|
-
resolveDir:
|
|
8637
|
+
resolveDir: path6.dirname(args2.path)
|
|
8624
8638
|
};
|
|
8625
8639
|
}
|
|
8626
8640
|
return null;
|
|
@@ -8657,8 +8671,8 @@ export { ${exportName} as __lua_target__ };
|
|
|
8657
8671
|
|
|
8658
8672
|
// src/compiler/agent-traverser.ts
|
|
8659
8673
|
import { Project as Project2, Node as Node16 } from "ts-morph";
|
|
8660
|
-
import
|
|
8661
|
-
import
|
|
8674
|
+
import path7 from "path";
|
|
8675
|
+
import fs8 from "fs";
|
|
8662
8676
|
var PRIMITIVE_TYPES, AgentTraverser;
|
|
8663
8677
|
var init_agent_traverser = __esm({
|
|
8664
8678
|
"src/compiler/agent-traverser.ts"() {
|
|
@@ -8731,7 +8745,7 @@ var init_agent_traverser = __esm({
|
|
|
8731
8745
|
this.rootDir = rootDir;
|
|
8732
8746
|
this.debug = debug;
|
|
8733
8747
|
this.project = new Project2({
|
|
8734
|
-
tsConfigFilePath:
|
|
8748
|
+
tsConfigFilePath: path7.join(rootDir, "tsconfig.json"),
|
|
8735
8749
|
skipAddingFilesFromTsConfig: true
|
|
8736
8750
|
});
|
|
8737
8751
|
registerProjectRootDir(this.project, this.rootDir);
|
|
@@ -8815,15 +8829,15 @@ var init_agent_traverser = __esm({
|
|
|
8815
8829
|
*/
|
|
8816
8830
|
detectAgent() {
|
|
8817
8831
|
const priorityFiles = [
|
|
8818
|
-
|
|
8819
|
-
|
|
8820
|
-
|
|
8821
|
-
|
|
8822
|
-
|
|
8823
|
-
|
|
8832
|
+
path7.join(this.rootDir, "index.ts"),
|
|
8833
|
+
path7.join(this.rootDir, "src", "index.ts"),
|
|
8834
|
+
path7.join(this.rootDir, "agent.ts"),
|
|
8835
|
+
path7.join(this.rootDir, "src", "agent.ts"),
|
|
8836
|
+
path7.join(this.rootDir, "main.ts"),
|
|
8837
|
+
path7.join(this.rootDir, "src", "main.ts")
|
|
8824
8838
|
];
|
|
8825
8839
|
for (const filePath of priorityFiles) {
|
|
8826
|
-
if (
|
|
8840
|
+
if (fs8.existsSync(filePath)) {
|
|
8827
8841
|
try {
|
|
8828
8842
|
const sourceFile = this.project.addSourceFileAtPath(filePath);
|
|
8829
8843
|
const agent = this.detectAgentInFile(sourceFile);
|
|
@@ -8975,7 +8989,7 @@ var init_agent_traverser = __esm({
|
|
|
8975
8989
|
console.warn(formatSarifWarning({
|
|
8976
8990
|
ruleId: "lua/missing-primitive-declaration",
|
|
8977
8991
|
filePath: sourcePath,
|
|
8978
|
-
message: `agent references ${kind} "${refName}" but ${
|
|
8992
|
+
message: `agent references ${kind} "${refName}" but ${path7.basename(sourcePath)} does not define a matching primitive`,
|
|
8979
8993
|
hint: `export a named ${plugin.displayName.toLowerCase()} declaration as "${refName}", or adjust the import so it points to the file that does`
|
|
8980
8994
|
}));
|
|
8981
8995
|
return null;
|
|
@@ -8995,20 +9009,20 @@ var init_agent_traverser = __esm({
|
|
|
8995
9009
|
});
|
|
8996
9010
|
|
|
8997
9011
|
// src/compiler/utils/workspace.ts
|
|
8998
|
-
import
|
|
8999
|
-
import
|
|
9012
|
+
import fs9 from "fs";
|
|
9013
|
+
import path8 from "path";
|
|
9000
9014
|
function findWorkspaceRoot(rootDir) {
|
|
9001
|
-
const resolvedInput =
|
|
9015
|
+
const resolvedInput = path8.resolve(rootDir);
|
|
9002
9016
|
const cached = workspaceRootCache.get(resolvedInput);
|
|
9003
9017
|
if (cached !== void 0) return cached;
|
|
9004
9018
|
let current = resolvedInput;
|
|
9005
|
-
const { root } =
|
|
9019
|
+
const { root } = path8.parse(current);
|
|
9006
9020
|
while (true) {
|
|
9007
9021
|
if (isWorkspaceRoot(current)) {
|
|
9008
9022
|
workspaceRootCache.set(resolvedInput, current);
|
|
9009
9023
|
return current;
|
|
9010
9024
|
}
|
|
9011
|
-
const parent =
|
|
9025
|
+
const parent = path8.dirname(current);
|
|
9012
9026
|
if (parent === current || current === root) break;
|
|
9013
9027
|
current = parent;
|
|
9014
9028
|
}
|
|
@@ -9016,22 +9030,22 @@ function findWorkspaceRoot(rootDir) {
|
|
|
9016
9030
|
return resolvedInput;
|
|
9017
9031
|
}
|
|
9018
9032
|
function isWorkspaceRoot(dir) {
|
|
9019
|
-
if (fileExists(
|
|
9020
|
-
if (fileExists(
|
|
9021
|
-
if (packageJsonHasWorkspaces(
|
|
9022
|
-
if (dirExists(
|
|
9033
|
+
if (fileExists(path8.join(dir, "pnpm-workspace.yaml"))) return true;
|
|
9034
|
+
if (fileExists(path8.join(dir, "lerna.json"))) return true;
|
|
9035
|
+
if (packageJsonHasWorkspaces(path8.join(dir, "package.json"))) return true;
|
|
9036
|
+
if (dirExists(path8.join(dir, ".git"))) return true;
|
|
9023
9037
|
return false;
|
|
9024
9038
|
}
|
|
9025
9039
|
function fileExists(p) {
|
|
9026
9040
|
try {
|
|
9027
|
-
return
|
|
9041
|
+
return fs9.statSync(p).isFile();
|
|
9028
9042
|
} catch {
|
|
9029
9043
|
return false;
|
|
9030
9044
|
}
|
|
9031
9045
|
}
|
|
9032
9046
|
function dirExists(p) {
|
|
9033
9047
|
try {
|
|
9034
|
-
return
|
|
9048
|
+
return fs9.statSync(p).isDirectory();
|
|
9035
9049
|
} catch {
|
|
9036
9050
|
return false;
|
|
9037
9051
|
}
|
|
@@ -9039,7 +9053,7 @@ function dirExists(p) {
|
|
|
9039
9053
|
function packageJsonHasWorkspaces(pkgPath) {
|
|
9040
9054
|
if (!fileExists(pkgPath)) return false;
|
|
9041
9055
|
try {
|
|
9042
|
-
const raw =
|
|
9056
|
+
const raw = fs9.readFileSync(pkgPath, "utf-8");
|
|
9043
9057
|
const json = JSON.parse(raw);
|
|
9044
9058
|
if (!json.workspaces) return false;
|
|
9045
9059
|
return Array.isArray(json.workspaces) || typeof json.workspaces === "object";
|
|
@@ -9061,8 +9075,8 @@ var init_workspace = __esm({
|
|
|
9061
9075
|
});
|
|
9062
9076
|
|
|
9063
9077
|
// src/compiler/compiler.ts
|
|
9064
|
-
import
|
|
9065
|
-
import
|
|
9078
|
+
import fs10 from "fs/promises";
|
|
9079
|
+
import path9 from "path";
|
|
9066
9080
|
import { Project as Project3 } from "ts-morph";
|
|
9067
9081
|
async function compile(options) {
|
|
9068
9082
|
const compiler = new Compiler(options);
|
|
@@ -9115,7 +9129,7 @@ var init_compiler = __esm({
|
|
|
9115
9129
|
...options
|
|
9116
9130
|
};
|
|
9117
9131
|
this.project = new Project3({
|
|
9118
|
-
tsConfigFilePath:
|
|
9132
|
+
tsConfigFilePath: path9.join(options.rootDir, "tsconfig.json")
|
|
9119
9133
|
});
|
|
9120
9134
|
registerProjectRootDir(this.project, this.options.rootDir);
|
|
9121
9135
|
this.bundler = new Bundler({
|
|
@@ -9192,10 +9206,10 @@ var init_compiler = __esm({
|
|
|
9192
9206
|
return await this.createResult(false, [], errors, warnings, startTime);
|
|
9193
9207
|
}
|
|
9194
9208
|
this.verbose("\u{1F4E6} Bundling primitives...");
|
|
9195
|
-
await
|
|
9209
|
+
await fs10.mkdir(this.options.outDir, {
|
|
9196
9210
|
recursive: true
|
|
9197
9211
|
});
|
|
9198
|
-
await
|
|
9212
|
+
await fs10.mkdir(path9.join(this.options.outDir, ".temp"), {
|
|
9199
9213
|
recursive: true
|
|
9200
9214
|
});
|
|
9201
9215
|
const CONCURRENCY = 4;
|
|
@@ -9215,7 +9229,7 @@ var init_compiler = __esm({
|
|
|
9215
9229
|
this.verbose("\u{1F4BE} Writing artifacts...");
|
|
9216
9230
|
await this.writeArtifacts(compiledPrimitives);
|
|
9217
9231
|
if (!this.options.debug) {
|
|
9218
|
-
await
|
|
9232
|
+
await fs10.rm(path9.join(this.options.outDir, ".temp"), {
|
|
9219
9233
|
recursive: true,
|
|
9220
9234
|
force: true
|
|
9221
9235
|
});
|
|
@@ -9258,7 +9272,7 @@ var init_compiler = __esm({
|
|
|
9258
9272
|
*/
|
|
9259
9273
|
getWorkspaceRoot() {
|
|
9260
9274
|
if (this._workspaceRoot === void 0) {
|
|
9261
|
-
this._workspaceRoot = findWorkspaceRoot(
|
|
9275
|
+
this._workspaceRoot = findWorkspaceRoot(path9.resolve(this.options.rootDir));
|
|
9262
9276
|
}
|
|
9263
9277
|
return this._workspaceRoot;
|
|
9264
9278
|
}
|
|
@@ -9272,18 +9286,18 @@ var init_compiler = __esm({
|
|
|
9272
9286
|
* - Files outside the detected workspace root (not our code)
|
|
9273
9287
|
*/
|
|
9274
9288
|
collectExternalWorkspaceFiles(traverser) {
|
|
9275
|
-
const rootDir =
|
|
9289
|
+
const rootDir = path9.resolve(this.options.rootDir);
|
|
9276
9290
|
const workspaceRoot = this.getWorkspaceRoot();
|
|
9277
9291
|
if (workspaceRoot === rootDir) return [];
|
|
9278
9292
|
const loaded = traverser.getAllLoadedSourceFilePaths();
|
|
9279
9293
|
const result = [];
|
|
9280
9294
|
const seen = /* @__PURE__ */ new Set();
|
|
9281
9295
|
for (const raw of loaded) {
|
|
9282
|
-
const abs =
|
|
9296
|
+
const abs = path9.resolve(raw);
|
|
9283
9297
|
if (seen.has(abs)) continue;
|
|
9284
9298
|
seen.add(abs);
|
|
9285
9299
|
if (isInside(abs, rootDir)) continue;
|
|
9286
|
-
if (abs.includes(`${
|
|
9300
|
+
if (abs.includes(`${path9.sep}node_modules${path9.sep}`)) continue;
|
|
9287
9301
|
if (!isInside(abs, workspaceRoot)) continue;
|
|
9288
9302
|
result.push(abs);
|
|
9289
9303
|
}
|
|
@@ -9416,9 +9430,9 @@ var init_compiler = __esm({
|
|
|
9416
9430
|
* @param primitives - All compiled primitives to write
|
|
9417
9431
|
*/
|
|
9418
9432
|
async writeArtifacts(primitives) {
|
|
9419
|
-
const artifactsDir =
|
|
9420
|
-
const sourcesDir =
|
|
9421
|
-
await
|
|
9433
|
+
const artifactsDir = path9.join(this.options.outDir, "artifacts");
|
|
9434
|
+
const sourcesDir = path9.join(this.options.outDir, "sources");
|
|
9435
|
+
await fs10.mkdir(sourcesDir, {
|
|
9422
9436
|
recursive: true
|
|
9423
9437
|
});
|
|
9424
9438
|
const writtenSources = /* @__PURE__ */ new Map();
|
|
@@ -9426,7 +9440,7 @@ var init_compiler = __esm({
|
|
|
9426
9440
|
this.verbose(" \u{1F4C2} Collecting project files...");
|
|
9427
9441
|
const projectFiles = await this.storeProjectFiles(sourcesDir, writtenSources);
|
|
9428
9442
|
const manifest = await this.createManifest(primitives, projectFiles);
|
|
9429
|
-
await
|
|
9443
|
+
await fs10.writeFile(path9.join(this.options.outDir, "manifest.json"), JSON.stringify(manifest, null, 2));
|
|
9430
9444
|
this.verbose(` \u{1F4E6} Total files stored: ${writtenSources.size} (deduplicated)`);
|
|
9431
9445
|
this.verbose(` \u{1F4C1} Project files: ${projectFiles.length}`);
|
|
9432
9446
|
if (this.options.verbose || this.options.debug) {
|
|
@@ -9438,25 +9452,25 @@ var init_compiler = __esm({
|
|
|
9438
9452
|
*/
|
|
9439
9453
|
async writePrimitiveArtifacts(primitives, artifactsDir, sourcesDir, writtenSources) {
|
|
9440
9454
|
for (const primitive of primitives) {
|
|
9441
|
-
const primitiveDir =
|
|
9442
|
-
await
|
|
9455
|
+
const primitiveDir = path9.join(artifactsDir, primitive.kind);
|
|
9456
|
+
await fs10.mkdir(primitiveDir, {
|
|
9443
9457
|
recursive: true
|
|
9444
9458
|
});
|
|
9445
9459
|
const baseName = primitive.name;
|
|
9446
|
-
await
|
|
9460
|
+
await fs10.writeFile(path9.join(primitiveDir, `${baseName}.js`), primitive.artifact.code);
|
|
9447
9461
|
if (primitive.artifact.sourceMap) {
|
|
9448
|
-
await
|
|
9462
|
+
await fs10.writeFile(path9.join(primitiveDir, `${baseName}.js.map`), primitive.artifact.sourceMap);
|
|
9449
9463
|
}
|
|
9450
9464
|
const sourceHash = hashContent(primitive.artifact.originalSource);
|
|
9451
9465
|
if (!writtenSources.has(sourceHash)) {
|
|
9452
9466
|
const ext = primitive.sourcePath.endsWith(".tsx") ? ".tsx" : ".ts";
|
|
9453
|
-
await
|
|
9454
|
-
const relativePath =
|
|
9467
|
+
await fs10.writeFile(path9.join(sourcesDir, `${sourceHash}${ext}`), primitive.artifact.originalSource);
|
|
9468
|
+
const relativePath = path9.relative(this.options.rootDir, primitive.sourcePath);
|
|
9455
9469
|
writtenSources.set(sourceHash, relativePath);
|
|
9456
9470
|
}
|
|
9457
9471
|
const sidecarPlugin = pluginRegistry.get(primitive.kind);
|
|
9458
9472
|
const sidecarMetadata = sidecarPlugin?.sanitizeForPersistence ? sidecarPlugin.sanitizeForPersistence(primitive.metadata) : primitive.metadata;
|
|
9459
|
-
await
|
|
9473
|
+
await fs10.writeFile(path9.join(primitiveDir, `${baseName}.json`), JSON.stringify({
|
|
9460
9474
|
kind: primitive.kind,
|
|
9461
9475
|
name: primitive.name,
|
|
9462
9476
|
description: primitive.description,
|
|
@@ -9478,12 +9492,12 @@ var init_compiler = __esm({
|
|
|
9478
9492
|
const allFiles = await this.collectProjectFiles();
|
|
9479
9493
|
const workspaceRoot = this.getWorkspaceRoot();
|
|
9480
9494
|
for (const file of allFiles) {
|
|
9481
|
-
const absPath = file.external ?
|
|
9482
|
-
const content = await
|
|
9495
|
+
const absPath = file.external ? path9.join(workspaceRoot, file.relativePath) : path9.join(this.options.rootDir, file.relativePath);
|
|
9496
|
+
const content = await fs10.readFile(absPath, "utf-8");
|
|
9483
9497
|
const hash = hashContent(content);
|
|
9484
9498
|
if (!writtenSources.has(hash)) {
|
|
9485
|
-
const ext =
|
|
9486
|
-
await
|
|
9499
|
+
const ext = path9.extname(file.relativePath) || ".txt";
|
|
9500
|
+
await fs10.writeFile(path9.join(sourcesDir, `${hash}${ext}`), content);
|
|
9487
9501
|
writtenSources.set(hash, file.relativePath);
|
|
9488
9502
|
}
|
|
9489
9503
|
projectFiles.push({
|
|
@@ -9559,12 +9573,12 @@ var init_compiler = __esm({
|
|
|
9559
9573
|
async collectProjectFiles() {
|
|
9560
9574
|
const files = [];
|
|
9561
9575
|
const scanDir = /* @__PURE__ */ __name(async (dir, relativeBase = "") => {
|
|
9562
|
-
const entries = await
|
|
9576
|
+
const entries = await fs10.readdir(dir, {
|
|
9563
9577
|
withFileTypes: true
|
|
9564
9578
|
});
|
|
9565
9579
|
for (const entry of entries) {
|
|
9566
9580
|
const relativePath = relativeBase ? `${relativeBase}/${entry.name}` : entry.name;
|
|
9567
|
-
const fullPath =
|
|
9581
|
+
const fullPath = path9.join(dir, entry.name);
|
|
9568
9582
|
if (entry.isDirectory()) {
|
|
9569
9583
|
if (shouldSkipDirectory(entry.name)) continue;
|
|
9570
9584
|
await scanDir(fullPath, relativePath);
|
|
@@ -9581,10 +9595,10 @@ var init_compiler = __esm({
|
|
|
9581
9595
|
const workspaceRoot = this.getWorkspaceRoot();
|
|
9582
9596
|
const externalSeen = /* @__PURE__ */ new Set();
|
|
9583
9597
|
for (const abs of this.externalWorkspaceFiles) {
|
|
9584
|
-
const rel =
|
|
9598
|
+
const rel = path9.relative(workspaceRoot, abs).split(path9.sep).join("/");
|
|
9585
9599
|
if (!rel || rel.startsWith("..")) continue;
|
|
9586
9600
|
if (externalSeen.has(rel)) continue;
|
|
9587
|
-
const name =
|
|
9601
|
+
const name = path9.basename(abs);
|
|
9588
9602
|
if (shouldSkipFile(rel) || shouldSkipFile(name)) continue;
|
|
9589
9603
|
externalSeen.add(rel);
|
|
9590
9604
|
files.push({
|
|
@@ -9685,13 +9699,13 @@ var init_compiler = __esm({
|
|
|
9685
9699
|
});
|
|
9686
9700
|
|
|
9687
9701
|
// src/compiler/utils/file-discovery.ts
|
|
9688
|
-
import
|
|
9689
|
-
import
|
|
9702
|
+
import path10 from "path";
|
|
9703
|
+
import fs11 from "fs";
|
|
9690
9704
|
function findEntryPoint(projectDir) {
|
|
9691
9705
|
const baseDir = projectDir || process.cwd();
|
|
9692
9706
|
for (const relativePath of ENTRY_POINT_PRIORITY) {
|
|
9693
|
-
const fullPath =
|
|
9694
|
-
if (
|
|
9707
|
+
const fullPath = path10.join(baseDir, relativePath);
|
|
9708
|
+
if (fs11.existsSync(fullPath)) {
|
|
9695
9709
|
return fullPath;
|
|
9696
9710
|
}
|
|
9697
9711
|
}
|
|
@@ -9728,8 +9742,8 @@ var init_file_discovery = __esm({
|
|
|
9728
9742
|
|
|
9729
9743
|
// src/compiler/source-writer.ts
|
|
9730
9744
|
import { Project as Project4, Node as Node17 } from "ts-morph";
|
|
9731
|
-
import
|
|
9732
|
-
import
|
|
9745
|
+
import fs12 from "fs";
|
|
9746
|
+
import path11 from "path";
|
|
9733
9747
|
function resolveEntryPath(options) {
|
|
9734
9748
|
let indexPath;
|
|
9735
9749
|
try {
|
|
@@ -9741,14 +9755,14 @@ function resolveEntryPath(options) {
|
|
|
9741
9755
|
indexPath = entryPoint;
|
|
9742
9756
|
} else {
|
|
9743
9757
|
const baseDir = options?.projectDir || process.cwd();
|
|
9744
|
-
indexPath =
|
|
9758
|
+
indexPath = path11.join(baseDir, "src", "index.ts");
|
|
9745
9759
|
}
|
|
9746
9760
|
}
|
|
9747
9761
|
} catch {
|
|
9748
9762
|
const baseDir = options?.projectDir || process.cwd();
|
|
9749
|
-
indexPath =
|
|
9763
|
+
indexPath = path11.join(baseDir, "src", "index.ts");
|
|
9750
9764
|
}
|
|
9751
|
-
if (!
|
|
9765
|
+
if (!fs12.existsSync(indexPath)) {
|
|
9752
9766
|
console.warn(`Warning: Entry file not found at ${indexPath}`);
|
|
9753
9767
|
return null;
|
|
9754
9768
|
}
|
|
@@ -13738,6 +13752,164 @@ __name(promptAuthMethod, "promptAuthMethod");
|
|
|
13738
13752
|
|
|
13739
13753
|
// src/commands/configure.ts
|
|
13740
13754
|
init_analytics();
|
|
13755
|
+
|
|
13756
|
+
// src/utils/versioning-mode-cache.ts
|
|
13757
|
+
import * as fs3 from "fs";
|
|
13758
|
+
import * as path3 from "path";
|
|
13759
|
+
|
|
13760
|
+
// src/api/agent-version.api.service.ts
|
|
13761
|
+
init_http_client();
|
|
13762
|
+
var AgentVersionApi = class extends HttpClient {
|
|
13763
|
+
static {
|
|
13764
|
+
__name(this, "AgentVersionApi");
|
|
13765
|
+
}
|
|
13766
|
+
apiKey;
|
|
13767
|
+
agentId;
|
|
13768
|
+
constructor(baseUrl, apiKey, agentId) {
|
|
13769
|
+
super(baseUrl);
|
|
13770
|
+
this.apiKey = apiKey;
|
|
13771
|
+
this.agentId = agentId;
|
|
13772
|
+
}
|
|
13773
|
+
get basePath() {
|
|
13774
|
+
return `/developer/agents/${encodeURIComponent(this.agentId)}`;
|
|
13775
|
+
}
|
|
13776
|
+
get authHeader() {
|
|
13777
|
+
return {
|
|
13778
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
13779
|
+
};
|
|
13780
|
+
}
|
|
13781
|
+
// ---------------------------------------------------------------------------
|
|
13782
|
+
// Versioning mode
|
|
13783
|
+
// ---------------------------------------------------------------------------
|
|
13784
|
+
async getVersioningMode() {
|
|
13785
|
+
return this.httpGet(`${this.basePath}/versioning/mode`, this.authHeader);
|
|
13786
|
+
}
|
|
13787
|
+
// ---------------------------------------------------------------------------
|
|
13788
|
+
// Version CRUD
|
|
13789
|
+
// ---------------------------------------------------------------------------
|
|
13790
|
+
async createVersion(body) {
|
|
13791
|
+
return this.httpPost(`${this.basePath}/versions`, body, this.authHeader);
|
|
13792
|
+
}
|
|
13793
|
+
async listVersions(query) {
|
|
13794
|
+
const params = new URLSearchParams();
|
|
13795
|
+
if (query?.all !== void 0) params.append("all", String(query.all));
|
|
13796
|
+
if (query?.limit !== void 0) params.append("limit", String(query.limit));
|
|
13797
|
+
if (query?.status !== void 0) params.append("status", query.status);
|
|
13798
|
+
const qs = params.toString();
|
|
13799
|
+
const url = qs ? `${this.basePath}/versions?${qs}` : `${this.basePath}/versions`;
|
|
13800
|
+
return this.httpGet(url, this.authHeader);
|
|
13801
|
+
}
|
|
13802
|
+
async getVersion(version) {
|
|
13803
|
+
return this.httpGet(`${this.basePath}/versions/${version}`, this.authHeader);
|
|
13804
|
+
}
|
|
13805
|
+
async deleteVersion(version) {
|
|
13806
|
+
return this.httpDelete(`${this.basePath}/versions/${version}`, this.authHeader);
|
|
13807
|
+
}
|
|
13808
|
+
// ---------------------------------------------------------------------------
|
|
13809
|
+
// Diff
|
|
13810
|
+
// ---------------------------------------------------------------------------
|
|
13811
|
+
async diffVersions(from, to) {
|
|
13812
|
+
const url = `${this.basePath}/versions/diff?from=${from}&to=${to}`;
|
|
13813
|
+
return this.httpGet(url, this.authHeader);
|
|
13814
|
+
}
|
|
13815
|
+
// ---------------------------------------------------------------------------
|
|
13816
|
+
// Promote
|
|
13817
|
+
// ---------------------------------------------------------------------------
|
|
13818
|
+
async promoteVersion(version) {
|
|
13819
|
+
return this.httpPost(`${this.basePath}/versions/${version}/promote`, {}, this.authHeader);
|
|
13820
|
+
}
|
|
13821
|
+
// ---------------------------------------------------------------------------
|
|
13822
|
+
// Patch commit hash — called by `lua version create` after a successful git
|
|
13823
|
+
// commit + tag to propagate the SHA to the backend AgentVersion record.
|
|
13824
|
+
// Failure is non-fatal; the version snapshot is valid whether or not this
|
|
13825
|
+
// PATCH lands.
|
|
13826
|
+
// ---------------------------------------------------------------------------
|
|
13827
|
+
async patchCommitHash(version, commitHash) {
|
|
13828
|
+
return this.httpPatch(`${this.basePath}/versions/${version}/commit-hash`, {
|
|
13829
|
+
commitHash
|
|
13830
|
+
}, this.authHeader);
|
|
13831
|
+
}
|
|
13832
|
+
};
|
|
13833
|
+
|
|
13834
|
+
// src/utils/versioning-mode-cache.ts
|
|
13835
|
+
init_constants();
|
|
13836
|
+
init_auth_error();
|
|
13837
|
+
init_constants();
|
|
13838
|
+
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
13839
|
+
function readCacheFile() {
|
|
13840
|
+
try {
|
|
13841
|
+
const raw = fs3.readFileSync(CLI_CACHE_FILE, "utf-8");
|
|
13842
|
+
return JSON.parse(raw);
|
|
13843
|
+
} catch {
|
|
13844
|
+
return {};
|
|
13845
|
+
}
|
|
13846
|
+
}
|
|
13847
|
+
__name(readCacheFile, "readCacheFile");
|
|
13848
|
+
function writeCacheFile(data) {
|
|
13849
|
+
try {
|
|
13850
|
+
fs3.mkdirSync(path3.dirname(CLI_CACHE_FILE), {
|
|
13851
|
+
recursive: true
|
|
13852
|
+
});
|
|
13853
|
+
fs3.writeFileSync(CLI_CACHE_FILE, JSON.stringify(data, null, 2));
|
|
13854
|
+
} catch {
|
|
13855
|
+
}
|
|
13856
|
+
}
|
|
13857
|
+
__name(writeCacheFile, "writeCacheFile");
|
|
13858
|
+
function isFresh(entry) {
|
|
13859
|
+
const age = Date.now() - new Date(entry.cachedAt).getTime();
|
|
13860
|
+
return age >= 0 && age < CACHE_TTL_MS;
|
|
13861
|
+
}
|
|
13862
|
+
__name(isFresh, "isFresh");
|
|
13863
|
+
async function getVersioningModeCached(apiKey, agentId) {
|
|
13864
|
+
const file = readCacheFile();
|
|
13865
|
+
const existing = file.versioningMode?.[agentId];
|
|
13866
|
+
if (existing && isFresh(existing)) {
|
|
13867
|
+
return {
|
|
13868
|
+
enabled: existing.enabled
|
|
13869
|
+
};
|
|
13870
|
+
}
|
|
13871
|
+
try {
|
|
13872
|
+
const api = new AgentVersionApi(BASE_URLS.API, apiKey, agentId);
|
|
13873
|
+
const response = await api.getVersioningMode();
|
|
13874
|
+
if (!response.success || !response.data) {
|
|
13875
|
+
if (existing) return {
|
|
13876
|
+
enabled: existing.enabled
|
|
13877
|
+
};
|
|
13878
|
+
return {
|
|
13879
|
+
enabled: false
|
|
13880
|
+
};
|
|
13881
|
+
}
|
|
13882
|
+
const enabled = response.data.enabled === true;
|
|
13883
|
+
file.versioningMode = file.versioningMode ?? {};
|
|
13884
|
+
file.versioningMode[agentId] = {
|
|
13885
|
+
enabled,
|
|
13886
|
+
cachedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
13887
|
+
};
|
|
13888
|
+
writeCacheFile(file);
|
|
13889
|
+
return {
|
|
13890
|
+
enabled
|
|
13891
|
+
};
|
|
13892
|
+
} catch (err) {
|
|
13893
|
+
if (err instanceof AuthenticationError) throw err;
|
|
13894
|
+
if (err instanceof Error && /access denied|forbidden|403|401/i.test(err.message)) throw err;
|
|
13895
|
+
if (existing) return {
|
|
13896
|
+
enabled: existing.enabled
|
|
13897
|
+
};
|
|
13898
|
+
return {
|
|
13899
|
+
enabled: false
|
|
13900
|
+
};
|
|
13901
|
+
}
|
|
13902
|
+
}
|
|
13903
|
+
__name(getVersioningModeCached, "getVersioningModeCached");
|
|
13904
|
+
function invalidateVersioningModeCache() {
|
|
13905
|
+
const file = readCacheFile();
|
|
13906
|
+
if (!file.versioningMode) return;
|
|
13907
|
+
delete file.versioningMode;
|
|
13908
|
+
writeCacheFile(file);
|
|
13909
|
+
}
|
|
13910
|
+
__name(invalidateVersioningModeCache, "invalidateVersioningModeCache");
|
|
13911
|
+
|
|
13912
|
+
// src/commands/configure.ts
|
|
13741
13913
|
async function configureCommand(options = {}) {
|
|
13742
13914
|
return withErrorHandling(async () => {
|
|
13743
13915
|
const { apiKey, email, otp } = options;
|
|
@@ -13747,11 +13919,13 @@ async function configureCommand(options = {}) {
|
|
|
13747
13919
|
authMethod = "api-key";
|
|
13748
13920
|
nonInteractive = true;
|
|
13749
13921
|
await handleApiKeyAuthNonInteractive(apiKey);
|
|
13922
|
+
invalidateVersioningModeCache();
|
|
13750
13923
|
} else if (email) {
|
|
13751
13924
|
authMethod = "email";
|
|
13752
13925
|
nonInteractive = true;
|
|
13753
13926
|
if (otp) {
|
|
13754
13927
|
await handleEmailOtpVerify(email, otp);
|
|
13928
|
+
invalidateVersioningModeCache();
|
|
13755
13929
|
} else {
|
|
13756
13930
|
await handleEmailOtpRequest(email);
|
|
13757
13931
|
}
|
|
@@ -13760,8 +13934,10 @@ async function configureCommand(options = {}) {
|
|
|
13760
13934
|
clearPromptLines(2);
|
|
13761
13935
|
if (authMethod === "api-key") {
|
|
13762
13936
|
await handleApiKeyAuth();
|
|
13937
|
+
invalidateVersioningModeCache();
|
|
13763
13938
|
} else if (authMethod === "email") {
|
|
13764
13939
|
await handleEmailAuth();
|
|
13940
|
+
invalidateVersioningModeCache();
|
|
13765
13941
|
}
|
|
13766
13942
|
}
|
|
13767
13943
|
trackEvent("cli_auth_completed", {
|
|
@@ -14433,8 +14609,8 @@ init_compile_constants();
|
|
|
14433
14609
|
init_artifact_loader();
|
|
14434
14610
|
init_backup_api_service();
|
|
14435
14611
|
init_constants();
|
|
14436
|
-
import
|
|
14437
|
-
import
|
|
14612
|
+
import fs13 from "fs";
|
|
14613
|
+
import path12 from "path";
|
|
14438
14614
|
var BACKUP_CACHE_FILENAME = "backup-manifest.json";
|
|
14439
14615
|
function calculateProjectHash(projectFiles) {
|
|
14440
14616
|
return combineFileHashes(projectFiles);
|
|
@@ -14447,11 +14623,11 @@ function getCurrentProjectHash(projectPath = process.cwd()) {
|
|
|
14447
14623
|
}
|
|
14448
14624
|
__name(getCurrentProjectHash, "getCurrentProjectHash");
|
|
14449
14625
|
function loadSourceByHash(hash, relativePath, projectPath = process.cwd()) {
|
|
14450
|
-
const sourcesDir =
|
|
14451
|
-
const ext =
|
|
14452
|
-
const sourcePath =
|
|
14453
|
-
if (
|
|
14454
|
-
return
|
|
14626
|
+
const sourcesDir = path12.join(projectPath, COMPILE_DIRS.DIST_V2, "sources");
|
|
14627
|
+
const ext = path12.extname(relativePath) || ".txt";
|
|
14628
|
+
const sourcePath = path12.join(sourcesDir, `${hash}${ext}`);
|
|
14629
|
+
if (fs13.existsSync(sourcePath)) {
|
|
14630
|
+
return fs13.readFileSync(sourcePath, "utf-8");
|
|
14455
14631
|
}
|
|
14456
14632
|
return null;
|
|
14457
14633
|
}
|
|
@@ -14470,30 +14646,30 @@ function prepareFileRefs(projectPath = process.cwd()) {
|
|
|
14470
14646
|
}
|
|
14471
14647
|
__name(prepareFileRefs, "prepareFileRefs");
|
|
14472
14648
|
function reconcileManifestWithDisk(projectPath = process.cwd()) {
|
|
14473
|
-
const manifestPath =
|
|
14474
|
-
if (!
|
|
14649
|
+
const manifestPath = path12.join(projectPath, COMPILE_DIRS.DIST_V2, "manifest.json");
|
|
14650
|
+
if (!fs13.existsSync(manifestPath)) return;
|
|
14475
14651
|
const manifest = loadManifest(projectPath);
|
|
14476
|
-
const sourcesDir =
|
|
14477
|
-
|
|
14652
|
+
const sourcesDir = path12.join(projectPath, COMPILE_DIRS.DIST_V2, "sources");
|
|
14653
|
+
fs13.mkdirSync(sourcesDir, {
|
|
14478
14654
|
recursive: true
|
|
14479
14655
|
});
|
|
14480
14656
|
let changed = false;
|
|
14481
14657
|
for (const file of manifest.projectFiles) {
|
|
14482
14658
|
if (file.external) continue;
|
|
14483
|
-
const absPath =
|
|
14484
|
-
if (!
|
|
14659
|
+
const absPath = path12.join(projectPath, file.relativePath);
|
|
14660
|
+
if (!fs13.existsSync(absPath)) continue;
|
|
14485
14661
|
let content;
|
|
14486
14662
|
try {
|
|
14487
|
-
content =
|
|
14663
|
+
content = fs13.readFileSync(absPath, "utf-8");
|
|
14488
14664
|
} catch {
|
|
14489
14665
|
continue;
|
|
14490
14666
|
}
|
|
14491
14667
|
const freshHash = hashContent(content);
|
|
14492
14668
|
if (freshHash === file.hash) continue;
|
|
14493
|
-
const ext =
|
|
14494
|
-
const sourceTargetPath =
|
|
14669
|
+
const ext = path12.extname(file.relativePath) || ".txt";
|
|
14670
|
+
const sourceTargetPath = path12.join(sourcesDir, `${freshHash}${ext}`);
|
|
14495
14671
|
try {
|
|
14496
|
-
|
|
14672
|
+
fs13.writeFileSync(sourceTargetPath, content, "utf-8");
|
|
14497
14673
|
} catch {
|
|
14498
14674
|
continue;
|
|
14499
14675
|
}
|
|
@@ -14502,7 +14678,7 @@ function reconcileManifestWithDisk(projectPath = process.cwd()) {
|
|
|
14502
14678
|
changed = true;
|
|
14503
14679
|
}
|
|
14504
14680
|
if (changed) {
|
|
14505
|
-
|
|
14681
|
+
fs13.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
14506
14682
|
}
|
|
14507
14683
|
}
|
|
14508
14684
|
__name(reconcileManifestWithDisk, "reconcileManifestWithDisk");
|
|
@@ -14575,7 +14751,7 @@ function checkRestoreConflicts(manifest, targetDir) {
|
|
|
14575
14751
|
const existingFiles = [];
|
|
14576
14752
|
for (const file of manifest.files) {
|
|
14577
14753
|
const filePath = resolveBackupFileTarget2(file, targetDir);
|
|
14578
|
-
if (
|
|
14754
|
+
if (fs13.existsSync(filePath)) {
|
|
14579
14755
|
existingFiles.push(file.relativePath);
|
|
14580
14756
|
} else {
|
|
14581
14757
|
newFiles.push(file.relativePath);
|
|
@@ -14601,16 +14777,16 @@ function createBackupTracking(projectHash) {
|
|
|
14601
14777
|
}
|
|
14602
14778
|
__name(createBackupTracking, "createBackupTracking");
|
|
14603
14779
|
function getBackupCachePath(projectPath = process.cwd()) {
|
|
14604
|
-
return
|
|
14780
|
+
return path12.join(projectPath, ".lua", BACKUP_CACHE_FILENAME);
|
|
14605
14781
|
}
|
|
14606
14782
|
__name(getBackupCachePath, "getBackupCachePath");
|
|
14607
14783
|
function writeBackupManifestCache(cache, projectPath = process.cwd()) {
|
|
14608
14784
|
const cachePath = getBackupCachePath(projectPath);
|
|
14609
14785
|
try {
|
|
14610
|
-
|
|
14786
|
+
fs13.mkdirSync(path12.dirname(cachePath), {
|
|
14611
14787
|
recursive: true
|
|
14612
14788
|
});
|
|
14613
|
-
|
|
14789
|
+
fs13.writeFileSync(cachePath, JSON.stringify(cache, null, 2), "utf-8");
|
|
14614
14790
|
} catch (error) {
|
|
14615
14791
|
const message = error instanceof Error ? error.message : String(error);
|
|
14616
14792
|
console.warn(`Could not write backup manifest cache: ${message}`);
|
|
@@ -14619,9 +14795,9 @@ function writeBackupManifestCache(cache, projectPath = process.cwd()) {
|
|
|
14619
14795
|
__name(writeBackupManifestCache, "writeBackupManifestCache");
|
|
14620
14796
|
function readBackupManifestCache(projectPath = process.cwd()) {
|
|
14621
14797
|
const cachePath = getBackupCachePath(projectPath);
|
|
14622
|
-
if (!
|
|
14798
|
+
if (!fs13.existsSync(cachePath)) return null;
|
|
14623
14799
|
try {
|
|
14624
|
-
const raw =
|
|
14800
|
+
const raw = fs13.readFileSync(cachePath, "utf-8");
|
|
14625
14801
|
const parsed = JSON.parse(raw);
|
|
14626
14802
|
if (typeof parsed.lastHash !== "string" || typeof parsed.lastPushedAt !== "string" || !Array.isArray(parsed.files) || !parsed.files.every((f) => f && typeof f.relativePath === "string" && typeof f.hash === "string")) {
|
|
14627
14803
|
return null;
|
|
@@ -14648,18 +14824,18 @@ function detectLocalConflictsForPull(incomingFiles, projectPath = process.cwd())
|
|
|
14648
14824
|
f.hash
|
|
14649
14825
|
]));
|
|
14650
14826
|
const conflicts = /* @__PURE__ */ new Set();
|
|
14651
|
-
const projectRoot =
|
|
14827
|
+
const projectRoot = path12.resolve(projectPath);
|
|
14652
14828
|
for (const incoming of incomingFiles) {
|
|
14653
14829
|
if (COMPILE_MANAGED_FILES.has(incoming.relativePath)) continue;
|
|
14654
14830
|
if (incoming.external) continue;
|
|
14655
|
-
const absPath =
|
|
14656
|
-
if (absPath !== projectRoot && !absPath.startsWith(projectRoot +
|
|
14831
|
+
const absPath = path12.resolve(projectRoot, incoming.relativePath);
|
|
14832
|
+
if (absPath !== projectRoot && !absPath.startsWith(projectRoot + path12.sep)) {
|
|
14657
14833
|
continue;
|
|
14658
14834
|
}
|
|
14659
|
-
if (!
|
|
14835
|
+
if (!fs13.existsSync(absPath)) continue;
|
|
14660
14836
|
let diskHash;
|
|
14661
14837
|
try {
|
|
14662
|
-
const bytes =
|
|
14838
|
+
const bytes = fs13.readFileSync(absPath, "utf-8");
|
|
14663
14839
|
diskHash = hashContent(bytes);
|
|
14664
14840
|
} catch {
|
|
14665
14841
|
conflicts.add(incoming.relativePath);
|
|
@@ -14686,7 +14862,7 @@ function detectLocalConflictsForPull(incomingFiles, projectPath = process.cwd())
|
|
|
14686
14862
|
__name(detectLocalConflictsForPull, "detectLocalConflictsForPull");
|
|
14687
14863
|
async function fetchBackupManifestForPull(apiKey, agentId) {
|
|
14688
14864
|
try {
|
|
14689
|
-
const backupApi = new
|
|
14865
|
+
const backupApi = new backup_api_service_default(BASE_URLS.API, apiKey, agentId);
|
|
14690
14866
|
const response = await backupApi.getBackupManifest();
|
|
14691
14867
|
return {
|
|
14692
14868
|
fetched: response.data ?? null
|
|
@@ -14717,7 +14893,7 @@ __name(decideBackupFreshness, "decideBackupFreshness");
|
|
|
14717
14893
|
async function checkServerBackupNewerThanLocal(apiKey, agentId, projectPath = process.cwd()) {
|
|
14718
14894
|
const local = readBackupManifestCache(projectPath);
|
|
14719
14895
|
try {
|
|
14720
|
-
const api = new
|
|
14896
|
+
const api = new backup_api_service_default(BASE_URLS.API, apiKey, agentId);
|
|
14721
14897
|
const resp = await api.getBackupMetadata();
|
|
14722
14898
|
const metadata = resp.success && resp.data ? {
|
|
14723
14899
|
projectHash: resp.data.projectHash
|
|
@@ -14730,7 +14906,7 @@ async function checkServerBackupNewerThanLocal(apiKey, agentId, projectPath = pr
|
|
|
14730
14906
|
__name(checkServerBackupNewerThanLocal, "checkServerBackupNewerThanLocal");
|
|
14731
14907
|
async function checkBackupAvailability(apiKey, agentId) {
|
|
14732
14908
|
try {
|
|
14733
|
-
const backupApi = new
|
|
14909
|
+
const backupApi = new backup_api_service_default(BASE_URLS.API, apiKey, agentId);
|
|
14734
14910
|
const metadata = await backupApi.getBackupMetadata();
|
|
14735
14911
|
if (metadata.data && metadata.data.fileCount > 0) {
|
|
14736
14912
|
return {
|
|
@@ -14752,7 +14928,7 @@ __name(checkBackupAvailability, "checkBackupAvailability");
|
|
|
14752
14928
|
async function restoreFromBackupForSync(apiKey, agentId, expectedPrimitives = [], projectPath, preFetchedManifest) {
|
|
14753
14929
|
const targetDir = projectPath || process.cwd();
|
|
14754
14930
|
try {
|
|
14755
|
-
const backupApi = new
|
|
14931
|
+
const backupApi = new backup_api_service_default(BASE_URLS.API, apiKey, agentId);
|
|
14756
14932
|
const manifest = preFetchedManifest ?? (await backupApi.getBackupManifest()).data ?? null;
|
|
14757
14933
|
if (!manifest || !manifest.files?.length) {
|
|
14758
14934
|
return {
|
|
@@ -14838,17 +15014,17 @@ function writeBackupFilesWithByteCompare(manifest, blobs, targetDir) {
|
|
|
14838
15014
|
}
|
|
14839
15015
|
restoredContents.set(makeRestoredContentsKey(file), content);
|
|
14840
15016
|
const filePath = resolveBackupFileTarget2(file, targetDir);
|
|
14841
|
-
if (
|
|
14842
|
-
const existing =
|
|
15017
|
+
if (fs13.existsSync(filePath)) {
|
|
15018
|
+
const existing = fs13.readFileSync(filePath);
|
|
14843
15019
|
if (existing.equals(content)) {
|
|
14844
15020
|
filesUnchanged++;
|
|
14845
15021
|
continue;
|
|
14846
15022
|
}
|
|
14847
15023
|
}
|
|
14848
|
-
|
|
15024
|
+
fs13.mkdirSync(path12.dirname(filePath), {
|
|
14849
15025
|
recursive: true
|
|
14850
15026
|
});
|
|
14851
|
-
|
|
15027
|
+
fs13.writeFileSync(filePath, content);
|
|
14852
15028
|
filesWritten++;
|
|
14853
15029
|
}
|
|
14854
15030
|
return {
|
|
@@ -16574,7 +16750,7 @@ async function checkAndRestoreBackup(apiKey, agentId, options) {
|
|
|
16574
16750
|
if (!confirm) return false;
|
|
16575
16751
|
}
|
|
16576
16752
|
try {
|
|
16577
|
-
const backupApi = new
|
|
16753
|
+
const backupApi = new backup_api_service_default(BASE_URLS.API, apiKey, agentId);
|
|
16578
16754
|
const urlsResponse = await backupApi.getBlobUrls(manifest.files.map((f) => f.hash));
|
|
16579
16755
|
if (!urlsResponse.success || !urlsResponse.data) {
|
|
16580
16756
|
writeError(`Failed to fetch download URLs: ${urlsResponse.error?.message ?? "unknown error"}`);
|
|
@@ -16628,6 +16804,7 @@ async function destroyCommand(options) {
|
|
|
16628
16804
|
if (options?.force) {
|
|
16629
16805
|
const deleted2 = deleteApiKey();
|
|
16630
16806
|
if (deleted2) {
|
|
16807
|
+
invalidateVersioningModeCache();
|
|
16631
16808
|
writeSuccess("\u2705 API key deleted successfully.");
|
|
16632
16809
|
} else {
|
|
16633
16810
|
writeProgress("\u274C Failed to delete API key.");
|
|
@@ -16653,6 +16830,7 @@ async function destroyCommand(options) {
|
|
|
16653
16830
|
if (confirm) {
|
|
16654
16831
|
deleted = deleteApiKey();
|
|
16655
16832
|
if (deleted) {
|
|
16833
|
+
invalidateVersioningModeCache();
|
|
16656
16834
|
writeSuccess("\u2705 API key deleted successfully.");
|
|
16657
16835
|
} else {
|
|
16658
16836
|
writeProgress("\u274C Failed to delete API key.");
|
|
@@ -16723,13 +16901,13 @@ __name(apiKeyCommand, "apiKeyCommand");
|
|
|
16723
16901
|
init_cli();
|
|
16724
16902
|
init_files();
|
|
16725
16903
|
init_auth();
|
|
16726
|
-
import
|
|
16904
|
+
import path14 from "path";
|
|
16727
16905
|
|
|
16728
16906
|
// src/commands/sync.ts
|
|
16729
16907
|
init_dist();
|
|
16730
16908
|
init_cli();
|
|
16731
|
-
import
|
|
16732
|
-
import
|
|
16909
|
+
import fs14 from "fs";
|
|
16910
|
+
import path13 from "path";
|
|
16733
16911
|
|
|
16734
16912
|
// src/utils/prompt-handler.ts
|
|
16735
16913
|
init_cli();
|
|
@@ -16940,8 +17118,8 @@ init_mcp_server_handler();
|
|
|
16940
17118
|
async function syncCommand(options) {
|
|
16941
17119
|
return withErrorHandling(async () => {
|
|
16942
17120
|
const preCompileYaml = readYamlConfig();
|
|
16943
|
-
const yamlPath =
|
|
16944
|
-
const preCompileYamlBytes =
|
|
17121
|
+
const yamlPath = path13.resolve(process.cwd(), "lua.skill.yaml");
|
|
17122
|
+
const preCompileYamlBytes = fs14.existsSync(yamlPath) ? fs14.readFileSync(yamlPath, "utf-8") : null;
|
|
16945
17123
|
let syncCompletedSuccessfully = false;
|
|
16946
17124
|
try {
|
|
16947
17125
|
writeProgress("\u{1F504} Compiling to get latest local state...");
|
|
@@ -17002,7 +17180,7 @@ async function syncCommand(options) {
|
|
|
17002
17180
|
} finally {
|
|
17003
17181
|
if (!syncCompletedSuccessfully && preCompileYamlBytes !== null) {
|
|
17004
17182
|
try {
|
|
17005
|
-
|
|
17183
|
+
fs14.writeFileSync(yamlPath, preCompileYamlBytes, "utf-8");
|
|
17006
17184
|
} catch {
|
|
17007
17185
|
}
|
|
17008
17186
|
}
|
|
@@ -18559,7 +18737,7 @@ async function compileCommand(options) {
|
|
|
18559
18737
|
}
|
|
18560
18738
|
writeProgress("\u{1F528} Compiling...");
|
|
18561
18739
|
const rootDir = process.cwd();
|
|
18562
|
-
const outDir =
|
|
18740
|
+
const outDir = path14.join(rootDir, "dist-v2");
|
|
18563
18741
|
const result = await compile({
|
|
18564
18742
|
rootDir,
|
|
18565
18743
|
outDir,
|
|
@@ -18723,12 +18901,12 @@ init_command_utils();
|
|
|
18723
18901
|
|
|
18724
18902
|
// src/utils/sandbox.ts
|
|
18725
18903
|
import vm3 from "vm";
|
|
18726
|
-
import
|
|
18904
|
+
import path17 from "path";
|
|
18727
18905
|
|
|
18728
18906
|
// ../shared-sandbox/dist/index.mjs
|
|
18729
18907
|
import vm from "vm";
|
|
18730
18908
|
import { createRequire } from "module";
|
|
18731
|
-
import
|
|
18909
|
+
import path15 from "path";
|
|
18732
18910
|
import dns from "dns";
|
|
18733
18911
|
import net from "net";
|
|
18734
18912
|
import { promisify } from "util";
|
|
@@ -18898,7 +19076,7 @@ var REQUIRE_BLOCKLIST = /* @__PURE__ */ new Set([
|
|
|
18898
19076
|
var SANDBOX_FAKE_DIRNAME = "/";
|
|
18899
19077
|
var SANDBOX_FAKE_FILENAME = "/index.ts";
|
|
18900
19078
|
function buildSandboxRequire(opts) {
|
|
18901
|
-
const realRequire = createRequire(
|
|
19079
|
+
const realRequire = createRequire(path15.join(opts.cwd, "package.json"));
|
|
18902
19080
|
const wrapped = /* @__PURE__ */ __name4((id) => {
|
|
18903
19081
|
if (REQUIRE_BLOCKLIST.has(id)) {
|
|
18904
19082
|
const evt = {
|
|
@@ -19568,14 +19746,14 @@ __name(runBundleInContext, "runBundleInContext");
|
|
|
19568
19746
|
__name4(runBundleInContext, "runBundleInContext");
|
|
19569
19747
|
|
|
19570
19748
|
// src/utils/env-loader.utils.ts
|
|
19571
|
-
import
|
|
19572
|
-
import
|
|
19749
|
+
import path16 from "path";
|
|
19750
|
+
import fs15 from "fs";
|
|
19573
19751
|
function parseEnvFile(filePath) {
|
|
19574
|
-
if (!
|
|
19752
|
+
if (!fs15.existsSync(filePath)) {
|
|
19575
19753
|
return {};
|
|
19576
19754
|
}
|
|
19577
19755
|
try {
|
|
19578
|
-
const content =
|
|
19756
|
+
const content = fs15.readFileSync(filePath, "utf8");
|
|
19579
19757
|
if (!content.trim()) return {};
|
|
19580
19758
|
const envVars = {};
|
|
19581
19759
|
content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#")).forEach((line) => {
|
|
@@ -19601,7 +19779,7 @@ async function loadEnvironmentVariables(context) {
|
|
|
19601
19779
|
}
|
|
19602
19780
|
__name(loadEnvironmentVariables, "loadEnvironmentVariables");
|
|
19603
19781
|
function loadSandboxEnvVariables() {
|
|
19604
|
-
const envFilePath =
|
|
19782
|
+
const envFilePath = path16.join(process.cwd(), ".env");
|
|
19605
19783
|
const envMap = parseEnvFile(envFilePath);
|
|
19606
19784
|
return Object.entries(envMap).map(([key, value]) => ({
|
|
19607
19785
|
key,
|
|
@@ -19696,7 +19874,7 @@ function loadEnvironmentVariables2() {
|
|
|
19696
19874
|
envVars[key] = value;
|
|
19697
19875
|
}
|
|
19698
19876
|
}
|
|
19699
|
-
const envFilePath =
|
|
19877
|
+
const envFilePath = path17.join(process.cwd(), ".env");
|
|
19700
19878
|
const fileEnvVars = parseEnvFile(envFilePath);
|
|
19701
19879
|
Object.assign(envVars, fileEnvVars);
|
|
19702
19880
|
return envVars;
|
|
@@ -21582,6 +21760,7 @@ init_dist();
|
|
|
21582
21760
|
init_files();
|
|
21583
21761
|
init_cli();
|
|
21584
21762
|
init_command_utils();
|
|
21763
|
+
init_auth();
|
|
21585
21764
|
init_semver();
|
|
21586
21765
|
init_auth_error();
|
|
21587
21766
|
init_constants();
|
|
@@ -21648,7 +21827,7 @@ async function runBackupPush(opts) {
|
|
|
21648
21827
|
projectHash: manifestProjectHash
|
|
21649
21828
|
};
|
|
21650
21829
|
}
|
|
21651
|
-
const backupApi = new
|
|
21830
|
+
const backupApi = new backup_api_service_default(BASE_URLS.API, opts.apiKey, opts.agentId);
|
|
21652
21831
|
const allHashes = opts.fresh ? [
|
|
21653
21832
|
...new Set(fileRefs.map((f) => f.hash))
|
|
21654
21833
|
] : getAllFileHashes(projectPath);
|
|
@@ -21709,8 +21888,8 @@ async function runBackupPush(opts) {
|
|
|
21709
21888
|
}
|
|
21710
21889
|
__name(runBackupPush, "runBackupPush");
|
|
21711
21890
|
async function uploadBlobsFromDisk(uploadUrls, files, projectPath, concurrency = 10) {
|
|
21712
|
-
const
|
|
21713
|
-
const
|
|
21891
|
+
const fs17 = await import("fs");
|
|
21892
|
+
const path19 = await import("path");
|
|
21714
21893
|
const zlib2 = await import("zlib");
|
|
21715
21894
|
const hashToPath = /* @__PURE__ */ new Map();
|
|
21716
21895
|
for (const f of files) {
|
|
@@ -21724,8 +21903,8 @@ async function uploadBlobsFromDisk(uploadUrls, files, projectPath, concurrency =
|
|
|
21724
21903
|
if (!rel) {
|
|
21725
21904
|
throw new Error(`No file found for hash: ${hash}`);
|
|
21726
21905
|
}
|
|
21727
|
-
const abs =
|
|
21728
|
-
const content =
|
|
21906
|
+
const abs = path19.join(projectPath, rel);
|
|
21907
|
+
const content = fs17.readFileSync(abs);
|
|
21729
21908
|
const compressed = zlib2.gzipSync(content);
|
|
21730
21909
|
const response = await fetch(uploadUrls[hash], {
|
|
21731
21910
|
method: "PUT",
|
|
@@ -21816,6 +21995,262 @@ init_analytics();
|
|
|
21816
21995
|
init_dist2();
|
|
21817
21996
|
init_skills_api_service();
|
|
21818
21997
|
|
|
21998
|
+
// src/utils/try-git-commit.ts
|
|
21999
|
+
init_cli();
|
|
22000
|
+
init_files();
|
|
22001
|
+
|
|
22002
|
+
// src/utils/git.ts
|
|
22003
|
+
import { spawn } from "child_process";
|
|
22004
|
+
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
22005
|
+
async function runGit(args2, opts = {}) {
|
|
22006
|
+
return new Promise((resolve6, reject) => {
|
|
22007
|
+
const child = spawn("git", args2, {
|
|
22008
|
+
cwd: opts.cwd,
|
|
22009
|
+
shell: false,
|
|
22010
|
+
stdio: [
|
|
22011
|
+
"ignore",
|
|
22012
|
+
"pipe",
|
|
22013
|
+
"pipe"
|
|
22014
|
+
]
|
|
22015
|
+
});
|
|
22016
|
+
let stdout = "";
|
|
22017
|
+
let stderr = "";
|
|
22018
|
+
let settled = false;
|
|
22019
|
+
const timer = setTimeout(() => {
|
|
22020
|
+
settled = true;
|
|
22021
|
+
child.kill("SIGKILL");
|
|
22022
|
+
reject(new Error(`git ${args2.join(" ")} timed out after ${opts.timeout ?? DEFAULT_TIMEOUT_MS}ms`));
|
|
22023
|
+
}, opts.timeout ?? DEFAULT_TIMEOUT_MS);
|
|
22024
|
+
child.stdout?.on("data", (chunk) => {
|
|
22025
|
+
stdout += chunk.toString();
|
|
22026
|
+
});
|
|
22027
|
+
child.stdout?.on("error", (err) => {
|
|
22028
|
+
if (settled) return;
|
|
22029
|
+
settled = true;
|
|
22030
|
+
clearTimeout(timer);
|
|
22031
|
+
reject(err);
|
|
22032
|
+
});
|
|
22033
|
+
child.stderr?.on("data", (chunk) => {
|
|
22034
|
+
stderr += chunk.toString();
|
|
22035
|
+
});
|
|
22036
|
+
child.stderr?.on("error", () => {
|
|
22037
|
+
});
|
|
22038
|
+
child.on("error", (err) => {
|
|
22039
|
+
if (settled) return;
|
|
22040
|
+
settled = true;
|
|
22041
|
+
clearTimeout(timer);
|
|
22042
|
+
reject(err);
|
|
22043
|
+
});
|
|
22044
|
+
child.on("close", (code) => {
|
|
22045
|
+
if (settled) return;
|
|
22046
|
+
settled = true;
|
|
22047
|
+
clearTimeout(timer);
|
|
22048
|
+
resolve6({
|
|
22049
|
+
stdout,
|
|
22050
|
+
stderr,
|
|
22051
|
+
code: code ?? 0
|
|
22052
|
+
});
|
|
22053
|
+
});
|
|
22054
|
+
});
|
|
22055
|
+
}
|
|
22056
|
+
__name(runGit, "runGit");
|
|
22057
|
+
function classifyGitError(err, stderr = "") {
|
|
22058
|
+
if (err && typeof err === "object" && "code" in err && err.code === "ENOENT") {
|
|
22059
|
+
return "no-git";
|
|
22060
|
+
}
|
|
22061
|
+
const s = stderr.toLowerCase();
|
|
22062
|
+
if (s.includes("not a git repository")) return "no-repo";
|
|
22063
|
+
if (s.includes("head detached") || s.includes("does not point to a branch") || s.includes("src refspec head does not match")) return "detached-head";
|
|
22064
|
+
if (s.includes("pre-commit hook") || s.includes("hook failed")) return "hook-failed";
|
|
22065
|
+
if (s.includes("already exists")) return "tag-exists";
|
|
22066
|
+
if (s.includes("nothing to commit")) return "nothing-to-commit";
|
|
22067
|
+
if (s.includes("authentication failed") || s.includes("could not read username")) return "auth";
|
|
22068
|
+
return "unknown";
|
|
22069
|
+
}
|
|
22070
|
+
__name(classifyGitError, "classifyGitError");
|
|
22071
|
+
async function isGitAvailable() {
|
|
22072
|
+
try {
|
|
22073
|
+
const { code } = await runGit([
|
|
22074
|
+
"--version"
|
|
22075
|
+
]);
|
|
22076
|
+
return code === 0;
|
|
22077
|
+
} catch {
|
|
22078
|
+
return false;
|
|
22079
|
+
}
|
|
22080
|
+
}
|
|
22081
|
+
__name(isGitAvailable, "isGitAvailable");
|
|
22082
|
+
async function isInsideGitRepo(cwd) {
|
|
22083
|
+
try {
|
|
22084
|
+
const { code } = await runGit([
|
|
22085
|
+
"rev-parse",
|
|
22086
|
+
"--is-inside-work-tree"
|
|
22087
|
+
], {
|
|
22088
|
+
cwd
|
|
22089
|
+
});
|
|
22090
|
+
return code === 0;
|
|
22091
|
+
} catch {
|
|
22092
|
+
return false;
|
|
22093
|
+
}
|
|
22094
|
+
}
|
|
22095
|
+
__name(isInsideGitRepo, "isInsideGitRepo");
|
|
22096
|
+
async function gitUserConfigured(cwd) {
|
|
22097
|
+
const readOne = /* @__PURE__ */ __name(async (key) => {
|
|
22098
|
+
try {
|
|
22099
|
+
const { stdout, code } = await runGit([
|
|
22100
|
+
"config",
|
|
22101
|
+
"--get",
|
|
22102
|
+
key
|
|
22103
|
+
], {
|
|
22104
|
+
cwd
|
|
22105
|
+
});
|
|
22106
|
+
if (code !== 0) return void 0;
|
|
22107
|
+
const trimmed = stdout.trim();
|
|
22108
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
22109
|
+
} catch {
|
|
22110
|
+
return void 0;
|
|
22111
|
+
}
|
|
22112
|
+
}, "readOne");
|
|
22113
|
+
const [name, email] = await Promise.all([
|
|
22114
|
+
readOne("user.name"),
|
|
22115
|
+
readOne("user.email")
|
|
22116
|
+
]);
|
|
22117
|
+
return {
|
|
22118
|
+
name,
|
|
22119
|
+
email
|
|
22120
|
+
};
|
|
22121
|
+
}
|
|
22122
|
+
__name(gitUserConfigured, "gitUserConfigured");
|
|
22123
|
+
async function getCommitSha(cwd) {
|
|
22124
|
+
try {
|
|
22125
|
+
const { stdout, code } = await runGit([
|
|
22126
|
+
"rev-parse",
|
|
22127
|
+
"HEAD"
|
|
22128
|
+
], {
|
|
22129
|
+
cwd
|
|
22130
|
+
});
|
|
22131
|
+
if (code !== 0) return null;
|
|
22132
|
+
const sha = stdout.trim();
|
|
22133
|
+
return sha.length > 0 ? sha : null;
|
|
22134
|
+
} catch {
|
|
22135
|
+
return null;
|
|
22136
|
+
}
|
|
22137
|
+
}
|
|
22138
|
+
__name(getCommitSha, "getCommitSha");
|
|
22139
|
+
|
|
22140
|
+
// src/utils/try-git-commit.ts
|
|
22141
|
+
init_analytics();
|
|
22142
|
+
async function tryGitCommit(opts) {
|
|
22143
|
+
const config = readYamlConfig();
|
|
22144
|
+
if (!config?.git?.enabled) {
|
|
22145
|
+
return {
|
|
22146
|
+
committed: false
|
|
22147
|
+
};
|
|
22148
|
+
}
|
|
22149
|
+
const runOpts = {
|
|
22150
|
+
cwd: opts.cwd
|
|
22151
|
+
};
|
|
22152
|
+
if (!opts.allowEmpty) {
|
|
22153
|
+
try {
|
|
22154
|
+
const addResult = await runGit([
|
|
22155
|
+
"add",
|
|
22156
|
+
"-A"
|
|
22157
|
+
], runOpts);
|
|
22158
|
+
if (addResult.code !== 0) {
|
|
22159
|
+
const reason = classifyGitError(null, addResult.stderr);
|
|
22160
|
+
reportFailure("add", reason);
|
|
22161
|
+
return {
|
|
22162
|
+
committed: false
|
|
22163
|
+
};
|
|
22164
|
+
}
|
|
22165
|
+
} catch (err) {
|
|
22166
|
+
const reason = classifyGitError(err);
|
|
22167
|
+
reportFailure("add", reason);
|
|
22168
|
+
return {
|
|
22169
|
+
committed: false
|
|
22170
|
+
};
|
|
22171
|
+
}
|
|
22172
|
+
}
|
|
22173
|
+
const commitArgs = [
|
|
22174
|
+
"commit"
|
|
22175
|
+
];
|
|
22176
|
+
if (opts.allowEmpty) commitArgs.push("--allow-empty");
|
|
22177
|
+
commitArgs.push("-m", opts.message);
|
|
22178
|
+
try {
|
|
22179
|
+
const commitResult = await runGit(commitArgs, runOpts);
|
|
22180
|
+
if (commitResult.code !== 0) {
|
|
22181
|
+
const reason = classifyGitError(null, commitResult.stderr);
|
|
22182
|
+
if (reason !== "nothing-to-commit") {
|
|
22183
|
+
reportFailure("commit", reason);
|
|
22184
|
+
}
|
|
22185
|
+
return {
|
|
22186
|
+
committed: false
|
|
22187
|
+
};
|
|
22188
|
+
}
|
|
22189
|
+
} catch (err) {
|
|
22190
|
+
const reason = classifyGitError(err);
|
|
22191
|
+
if (reason !== "nothing-to-commit") {
|
|
22192
|
+
reportFailure("commit", reason);
|
|
22193
|
+
}
|
|
22194
|
+
return {
|
|
22195
|
+
committed: false
|
|
22196
|
+
};
|
|
22197
|
+
}
|
|
22198
|
+
const sha = await getCommitSha(opts.cwd) ?? void 0;
|
|
22199
|
+
let tagged;
|
|
22200
|
+
if (opts.tag) {
|
|
22201
|
+
try {
|
|
22202
|
+
const tagResult = await runGit([
|
|
22203
|
+
"tag",
|
|
22204
|
+
opts.tag
|
|
22205
|
+
], runOpts);
|
|
22206
|
+
if (tagResult.code !== 0) {
|
|
22207
|
+
const reason = classifyGitError(null, tagResult.stderr);
|
|
22208
|
+
reportFailure("tag", reason);
|
|
22209
|
+
tagged = false;
|
|
22210
|
+
} else {
|
|
22211
|
+
tagged = true;
|
|
22212
|
+
}
|
|
22213
|
+
} catch (err) {
|
|
22214
|
+
const reason = classifyGitError(err);
|
|
22215
|
+
reportFailure("tag", reason);
|
|
22216
|
+
tagged = false;
|
|
22217
|
+
}
|
|
22218
|
+
}
|
|
22219
|
+
trackEvent("cli_git_sideeffect_succeeded", {
|
|
22220
|
+
action: opts.action,
|
|
22221
|
+
has_sha: Boolean(sha),
|
|
22222
|
+
has_tag: tagged === true
|
|
22223
|
+
});
|
|
22224
|
+
return {
|
|
22225
|
+
committed: true,
|
|
22226
|
+
sha,
|
|
22227
|
+
tagged
|
|
22228
|
+
};
|
|
22229
|
+
}
|
|
22230
|
+
__name(tryGitCommit, "tryGitCommit");
|
|
22231
|
+
function reportFailure(action, reason) {
|
|
22232
|
+
writeInfo(`\u26A0\uFE0F Git ${action} skipped: ${reason}`);
|
|
22233
|
+
trackEvent("cli_git_sideeffect_failed", {
|
|
22234
|
+
action,
|
|
22235
|
+
reason
|
|
22236
|
+
});
|
|
22237
|
+
}
|
|
22238
|
+
__name(reportFailure, "reportFailure");
|
|
22239
|
+
|
|
22240
|
+
// src/utils/git-messages.ts
|
|
22241
|
+
var GIT_MESSAGES = {
|
|
22242
|
+
pushStaged: "lua: push staged code",
|
|
22243
|
+
createVersion: /* @__PURE__ */ __name((version, message) => {
|
|
22244
|
+
const trimmed = message?.trim();
|
|
22245
|
+
return trimmed ? `lua: create version v${version}: ${trimmed}` : `lua: create version v${version}`;
|
|
22246
|
+
}, "createVersion"),
|
|
22247
|
+
promote: /* @__PURE__ */ __name((version) => `lua: promote v${version} to production`, "promote"),
|
|
22248
|
+
delete: /* @__PURE__ */ __name((version) => `lua: delete version v${version}`, "delete"),
|
|
22249
|
+
pullLatest: "lua: pull latest backup",
|
|
22250
|
+
pullVersion: /* @__PURE__ */ __name((version) => `lua: pull version v${version}`, "pullVersion")
|
|
22251
|
+
};
|
|
22252
|
+
var tagName = /* @__PURE__ */ __name((version) => `lua/v${version}`, "tagName");
|
|
22253
|
+
|
|
21819
22254
|
// src/commands/push-helpers.ts
|
|
21820
22255
|
function pickPushAllNextStepVariant(opts) {
|
|
21821
22256
|
if (opts.pushedSomething && opts.failedCount === 0) return "success";
|
|
@@ -22130,6 +22565,34 @@ async function pushCommand(type, cmdObj) {
|
|
|
22130
22565
|
allowAll: true
|
|
22131
22566
|
});
|
|
22132
22567
|
}
|
|
22568
|
+
const earlyApiKey = loadApiKey();
|
|
22569
|
+
const earlyConfig = readYamlConfig();
|
|
22570
|
+
const earlyAgentId = earlyConfig?.agent?.agentId;
|
|
22571
|
+
const versioning = earlyApiKey && earlyAgentId ? await getVersioningModeCached(earlyApiKey, earlyAgentId) : {
|
|
22572
|
+
enabled: false
|
|
22573
|
+
};
|
|
22574
|
+
const isStageAll = !type && versioning.enabled;
|
|
22575
|
+
const isGranular = Boolean(type && type !== "all" && versioning.enabled);
|
|
22576
|
+
const isAutoDeployNoOp = versioning.enabled && (type === "all" || !type) && Boolean(options.autoDeploy);
|
|
22577
|
+
if (isAutoDeployNoOp) {
|
|
22578
|
+
writeInfo("\u26A0\uFE0F --auto-deploy is ignored when agent versioning is on. Use `lua version promote <version>` after `lua version create`.");
|
|
22579
|
+
options.autoDeploy = false;
|
|
22580
|
+
}
|
|
22581
|
+
if (options.entityName && !type) {
|
|
22582
|
+
console.log("\nUsage:");
|
|
22583
|
+
console.log(" lua push skill --name mySkill --set-version 1.0.5 Push specific skill");
|
|
22584
|
+
console.log(" lua push webhook --name myWebhook --set-version 2.0.0 Push specific webhook");
|
|
22585
|
+
throw new Error("Type must be specified when using the --name option.");
|
|
22586
|
+
}
|
|
22587
|
+
if (isStageAll) {
|
|
22588
|
+
return await pushAllCommand({
|
|
22589
|
+
...options,
|
|
22590
|
+
autoDeployNoopWarned: isAutoDeployNoOp
|
|
22591
|
+
});
|
|
22592
|
+
}
|
|
22593
|
+
if (isGranular) {
|
|
22594
|
+
writeInfo("\u26A0\uFE0F Granular push is deprecated when agent versioning is on. Use `lua push` (no args) to stage all changes, then `lua version create`.");
|
|
22595
|
+
}
|
|
22133
22596
|
if (type === "all") {
|
|
22134
22597
|
if (!options.force) {
|
|
22135
22598
|
console.log("\nUsage:");
|
|
@@ -22137,13 +22600,10 @@ async function pushCommand(type, cmdObj) {
|
|
|
22137
22600
|
console.log(" lua push all --force --auto-deploy Push and deploy all to production");
|
|
22138
22601
|
throw new Error('The "all" type requires the --force flag');
|
|
22139
22602
|
}
|
|
22140
|
-
return await pushAllCommand(
|
|
22141
|
-
|
|
22142
|
-
|
|
22143
|
-
|
|
22144
|
-
console.log(" lua push skill --name mySkill --set-version 1.0.5 Push specific skill");
|
|
22145
|
-
console.log(" lua push webhook --name myWebhook --set-version 2.0.0 Push specific webhook");
|
|
22146
|
-
throw new Error("Type must be specified when using the --name option.");
|
|
22603
|
+
return await pushAllCommand({
|
|
22604
|
+
...options,
|
|
22605
|
+
autoDeployNoopWarned: isAutoDeployNoOp
|
|
22606
|
+
});
|
|
22147
22607
|
}
|
|
22148
22608
|
if (type) {
|
|
22149
22609
|
selectedType = type;
|
|
@@ -22284,13 +22744,17 @@ Until the backup catches up, \`lua init\` for this agent will restore an older s
|
|
|
22284
22744
|
bundles_total: versionedPushDeployResult?.bundleStats?.total ?? 0,
|
|
22285
22745
|
bundles_uploaded: versionedPushDeployResult?.bundleStats?.uploaded ?? 0,
|
|
22286
22746
|
bundles_existed: versionedPushDeployResult?.bundleStats?.alreadyExisted ?? 0,
|
|
22287
|
-
//
|
|
22288
|
-
//
|
|
22289
|
-
//
|
|
22747
|
+
// `--include-source` telemetry. Tracks adoption of the flag and whether
|
|
22748
|
+
// the per-skill source attach actually lands cleanly — useful for the
|
|
22749
|
+
// eventual "flip default to ON" decision.
|
|
22290
22750
|
include_source_requested: options.includeSource || false,
|
|
22291
22751
|
include_source_attempted: trackedIncludeSource?.attempted ?? 0,
|
|
22292
22752
|
include_source_attached: trackedIncludeSource?.attached ?? 0,
|
|
22293
|
-
include_source_failed: trackedIncludeSource?.failed ?? 0
|
|
22753
|
+
include_source_failed: trackedIncludeSource?.failed ?? 0,
|
|
22754
|
+
// Agent-versioning telemetry. Driven by isStageAll / isGranular.
|
|
22755
|
+
versioning_mode: versioning.enabled ? isGranular ? "granular" : "all" : "flag-off",
|
|
22756
|
+
granular_deprecation_warned: isGranular,
|
|
22757
|
+
auto_deploy_noop_warned: isAutoDeployNoOp
|
|
22294
22758
|
});
|
|
22295
22759
|
const productionDeployedActually = versionedPushDeployResult?.productionDeploySucceeded === true || !!agentOutcome && !agentOutcome.cancelled && agentOutcome.productionDeployedWithAutoDeploy;
|
|
22296
22760
|
const personaAutoDeployRanAndFailed = selectedType === "agent" && options.autoDeploy && !!agentOutcome && !agentOutcome.cancelled && "personaAutoDeployFailed" in agentOutcome && agentOutcome.personaAutoDeployFailed;
|
|
@@ -22583,6 +23047,7 @@ async function pushAllCommand(options) {
|
|
|
22583
23047
|
}
|
|
22584
23048
|
const apiKey = await requireAuthOrExit(false);
|
|
22585
23049
|
const agentId = config.agent.agentId;
|
|
23050
|
+
const pushAllVersioning = await getVersioningModeCached(apiKey, agentId);
|
|
22586
23051
|
let manifest;
|
|
22587
23052
|
try {
|
|
22588
23053
|
manifest = loadManifest();
|
|
@@ -22879,15 +23344,26 @@ Until the backup catches up, \`lua init\` for this agent will restore an older s
|
|
|
22879
23344
|
bundles_total: bundleStatsAggregate.total,
|
|
22880
23345
|
bundles_uploaded: bundleStatsAggregate.uploaded,
|
|
22881
23346
|
bundles_existed: bundleStatsAggregate.existed,
|
|
22882
|
-
//
|
|
23347
|
+
// `--include-source` telemetry, parallel to the single-push
|
|
22883
23348
|
// `cli_push_completed` shape. Without these the `lua push all` path —
|
|
22884
|
-
//
|
|
22885
|
-
//
|
|
23349
|
+
// the highest-volume one for multi-skill agents — would be invisible
|
|
23350
|
+
// to adoption monitoring.
|
|
22886
23351
|
include_source_requested: options.includeSource || false,
|
|
22887
23352
|
include_source_attempted: includeSourceStats?.attempted ?? 0,
|
|
22888
23353
|
include_source_attached: includeSourceStats?.attached ?? 0,
|
|
22889
|
-
include_source_failed: includeSourceStats?.failed ?? 0
|
|
23354
|
+
include_source_failed: includeSourceStats?.failed ?? 0,
|
|
23355
|
+
// Agent-versioning telemetry.
|
|
23356
|
+
versioning_mode: pushAllVersioning.enabled ? "stage-all" : "flag-off",
|
|
23357
|
+
granular_deprecation_warned: false,
|
|
23358
|
+
auto_deploy_noop_warned: options.autoDeployNoopWarned || false
|
|
22890
23359
|
});
|
|
23360
|
+
try {
|
|
23361
|
+
await tryGitCommit({
|
|
23362
|
+
message: GIT_MESSAGES.pushStaged,
|
|
23363
|
+
action: "push-staged"
|
|
23364
|
+
});
|
|
23365
|
+
} catch {
|
|
23366
|
+
}
|
|
22891
23367
|
const pushedSomething = allResults.length > 0 || mcpPushedCount > 0 || !!personaPushResult || backupSuccess;
|
|
22892
23368
|
const variant = pickPushAllNextStepVariant({
|
|
22893
23369
|
pushedSomething,
|
|
@@ -22895,7 +23371,11 @@ Until the backup catches up, \`lua init\` for this agent will restore an older s
|
|
|
22895
23371
|
});
|
|
22896
23372
|
if (variant === "success") {
|
|
22897
23373
|
console.log("");
|
|
22898
|
-
if (
|
|
23374
|
+
if (pushAllVersioning.enabled) {
|
|
23375
|
+
if (!options.suppressVersionCreateHint) {
|
|
23376
|
+
writeInfo(`Run \`lua version create [-m "<message>"]\` to snapshot the staged state into a named version, then \`lua version promote <version>\` to deploy.`);
|
|
23377
|
+
}
|
|
23378
|
+
} else if (options.autoDeploy) {
|
|
22899
23379
|
writeHintBlock({
|
|
22900
23380
|
headline: "All deployed. Generate test traffic first, then inspect:",
|
|
22901
23381
|
lines: [
|
|
@@ -23163,6 +23643,10 @@ async function deployCommand(type, cmdObj) {
|
|
|
23163
23643
|
selectedType = answer.type;
|
|
23164
23644
|
}
|
|
23165
23645
|
const apiKey = await requireAuthOrExit();
|
|
23646
|
+
const versioning = await getVersioningModeCached(apiKey, agentId);
|
|
23647
|
+
if (versioning.enabled) {
|
|
23648
|
+
writeInfo("\u26A0\uFE0F `lua deploy` is deprecated when agent versioning is on. Use `lua version promote <version>` for instant, atomic promotion.");
|
|
23649
|
+
}
|
|
23166
23650
|
let personaDeployed = false;
|
|
23167
23651
|
let versionedOutcome = null;
|
|
23168
23652
|
if (selectedType === "persona") {
|
|
@@ -23175,7 +23659,8 @@ async function deployCommand(type, cmdObj) {
|
|
|
23175
23659
|
primitive_type: selectedType,
|
|
23176
23660
|
force_mode: options.force || false,
|
|
23177
23661
|
entity_selected_by_name: !!options.name,
|
|
23178
|
-
version_selected_by_flag: !!options.version
|
|
23662
|
+
version_selected_by_flag: !!options.version,
|
|
23663
|
+
granular_deprecation_warned: versioning.enabled
|
|
23179
23664
|
});
|
|
23180
23665
|
const deployed = selectedType === "persona" ? personaDeployed : versionedOutcome?.deployed ?? false;
|
|
23181
23666
|
const hintPrintedAlready = selectedType !== "persona" && !!versionedOutcome?.hintPrinted;
|
|
@@ -23669,11 +24154,11 @@ init_cli();
|
|
|
23669
24154
|
|
|
23670
24155
|
// src/utils/sandbox-storage.ts
|
|
23671
24156
|
init_constants();
|
|
23672
|
-
import { readFileSync as
|
|
23673
|
-
import { dirname as
|
|
24157
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7 } from "fs";
|
|
24158
|
+
import { dirname as dirname6 } from "path";
|
|
23674
24159
|
function readStore() {
|
|
23675
24160
|
try {
|
|
23676
|
-
const raw =
|
|
24161
|
+
const raw = readFileSync10(SANDBOX_STORAGE_FILE, "utf8");
|
|
23677
24162
|
const parsed = JSON.parse(raw);
|
|
23678
24163
|
return {
|
|
23679
24164
|
skills: parsed.skills ?? {},
|
|
@@ -23693,10 +24178,10 @@ function readStore() {
|
|
|
23693
24178
|
__name(readStore, "readStore");
|
|
23694
24179
|
function writeStore(store) {
|
|
23695
24180
|
try {
|
|
23696
|
-
|
|
24181
|
+
mkdirSync7(dirname6(SANDBOX_STORAGE_FILE), {
|
|
23697
24182
|
recursive: true
|
|
23698
24183
|
});
|
|
23699
|
-
|
|
24184
|
+
writeFileSync7(SANDBOX_STORAGE_FILE, JSON.stringify(store, null, 2), "utf8");
|
|
23700
24185
|
} catch {
|
|
23701
24186
|
}
|
|
23702
24187
|
}
|
|
@@ -24200,7 +24685,15 @@ var MIME_TYPES = {
|
|
|
24200
24685
|
".json": "application/json",
|
|
24201
24686
|
// Email
|
|
24202
24687
|
".eml": "message/rfc822",
|
|
24203
|
-
".msg": "application/vnd.ms-outlook"
|
|
24688
|
+
".msg": "application/vnd.ms-outlook",
|
|
24689
|
+
// Audio. lua-core picks the path per provider: types in the provider's
|
|
24690
|
+
// native allowlist go straight to the model, the rest are transcribed by
|
|
24691
|
+
// Deepgram via FileConversionService.
|
|
24692
|
+
".m4a": "audio/mp4",
|
|
24693
|
+
".mp3": "audio/mpeg",
|
|
24694
|
+
".wav": "audio/wav",
|
|
24695
|
+
".ogg": "audio/ogg",
|
|
24696
|
+
".opus": "audio/opus"
|
|
24204
24697
|
};
|
|
24205
24698
|
var IMAGE_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
24206
24699
|
"image/png",
|
|
@@ -25010,8 +25503,8 @@ init_cli();
|
|
|
25010
25503
|
init_constants();
|
|
25011
25504
|
init_command_utils();
|
|
25012
25505
|
init_developer_api_service();
|
|
25013
|
-
import
|
|
25014
|
-
import
|
|
25506
|
+
import fs16 from "fs";
|
|
25507
|
+
import path18 from "path";
|
|
25015
25508
|
import inquirer10 from "inquirer";
|
|
25016
25509
|
init_analytics();
|
|
25017
25510
|
function resolveEnvironment(env, hasNonInteractiveFlags) {
|
|
@@ -25370,10 +25863,10 @@ function variablesToEnvContent(variables) {
|
|
|
25370
25863
|
}
|
|
25371
25864
|
__name(variablesToEnvContent, "variablesToEnvContent");
|
|
25372
25865
|
function saveSandboxEnvVariables(variables) {
|
|
25373
|
-
const envFilePath =
|
|
25866
|
+
const envFilePath = path18.join(process.cwd(), ".env");
|
|
25374
25867
|
try {
|
|
25375
25868
|
const content = variablesToEnvContent(variables);
|
|
25376
|
-
|
|
25869
|
+
fs16.writeFileSync(envFilePath, content, "utf8");
|
|
25377
25870
|
return true;
|
|
25378
25871
|
} catch (error) {
|
|
25379
25872
|
console.error("\u274C Error saving .env file:", error);
|
|
@@ -29865,7 +30358,7 @@ init_auth();
|
|
|
29865
30358
|
init_auth_api_service();
|
|
29866
30359
|
init_files();
|
|
29867
30360
|
init_artifact_loader();
|
|
29868
|
-
import { existsSync as existsSync7, readFileSync as
|
|
30361
|
+
import { existsSync as existsSync7, readFileSync as readFileSync11 } from "fs";
|
|
29869
30362
|
import { join as join6 } from "path";
|
|
29870
30363
|
import { performance } from "perf_hooks";
|
|
29871
30364
|
import * as os from "os";
|
|
@@ -30216,7 +30709,7 @@ function gatherTelemetry() {
|
|
|
30216
30709
|
} else {
|
|
30217
30710
|
try {
|
|
30218
30711
|
if (existsSync7(TELEMETRY_FILE)) {
|
|
30219
|
-
const raw =
|
|
30712
|
+
const raw = readFileSync11(TELEMETRY_FILE, "utf8");
|
|
30220
30713
|
const cfg = JSON.parse(raw);
|
|
30221
30714
|
if (typeof cfg.enabled === "boolean") enabled = cfg.enabled;
|
|
30222
30715
|
}
|
|
@@ -39397,7 +39890,7 @@ __name(telemetryCommand, "telemetryCommand");
|
|
|
39397
39890
|
init_cli();
|
|
39398
39891
|
init_command_utils();
|
|
39399
39892
|
init_analytics();
|
|
39400
|
-
import { writeFileSync as
|
|
39893
|
+
import { writeFileSync as writeFileSync8, existsSync as existsSync8, unlinkSync as unlinkSync2 } from "fs";
|
|
39401
39894
|
import { resolve as resolve4, join as join7 } from "path";
|
|
39402
39895
|
init_artifact_loader();
|
|
39403
39896
|
init_types();
|
|
@@ -39558,7 +40051,7 @@ async function governanceCommand(action) {
|
|
|
39558
40051
|
}
|
|
39559
40052
|
}
|
|
39560
40053
|
const content = generateFile(setup);
|
|
39561
|
-
|
|
40054
|
+
writeFileSync8(filePath, content, "utf-8");
|
|
39562
40055
|
const relativePath = filePath.replace(process.cwd() + "/", "");
|
|
39563
40056
|
writeSuccess(`Created ${relativePath}`);
|
|
39564
40057
|
console.log("");
|
|
@@ -39822,14 +40315,14 @@ init_analytics();
|
|
|
39822
40315
|
init_command_utils();
|
|
39823
40316
|
init_artifact_loader();
|
|
39824
40317
|
init_types();
|
|
39825
|
-
import { spawn as
|
|
40318
|
+
import { spawn as spawn3 } from "child_process";
|
|
39826
40319
|
import { existsSync as existsSync9, readdirSync as readdirSync3, statSync as statSync4 } from "fs";
|
|
39827
40320
|
import { join as join8, relative, resolve as resolve5 } from "path";
|
|
39828
40321
|
init_voice_api_service();
|
|
39829
40322
|
init_constants();
|
|
39830
40323
|
|
|
39831
40324
|
// src/commands/voice-terminal.ts
|
|
39832
|
-
import { spawn, spawnSync } from "child_process";
|
|
40325
|
+
import { spawn as spawn2, spawnSync } from "child_process";
|
|
39833
40326
|
import { platform as platform3 } from "os";
|
|
39834
40327
|
import { AudioFrame, AudioSource, AudioStream, LocalAudioTrack, Room, RoomEvent, TrackKind, TrackPublishOptions, TrackSource } from "@livekit/rtc-node";
|
|
39835
40328
|
|
|
@@ -40092,7 +40585,7 @@ function spawnCapture() {
|
|
|
40092
40585
|
String(FRAME_SAMPLES * 2),
|
|
40093
40586
|
"-"
|
|
40094
40587
|
];
|
|
40095
|
-
const proc =
|
|
40588
|
+
const proc = spawn2("sox", args2, {
|
|
40096
40589
|
stdio: [
|
|
40097
40590
|
"ignore",
|
|
40098
40591
|
"pipe",
|
|
@@ -40123,7 +40616,7 @@ function spawnPlayback() {
|
|
|
40123
40616
|
"-",
|
|
40124
40617
|
"-d"
|
|
40125
40618
|
];
|
|
40126
|
-
const proc =
|
|
40619
|
+
const proc = spawn2("sox", args2, {
|
|
40127
40620
|
stdio: [
|
|
40128
40621
|
"pipe",
|
|
40129
40622
|
"ignore",
|
|
@@ -40453,7 +40946,7 @@ function buildRunnerArgs(runner, opts) {
|
|
|
40453
40946
|
__name(buildRunnerArgs, "buildRunnerArgs");
|
|
40454
40947
|
async function spawnRunner(runner, args2, cwd) {
|
|
40455
40948
|
return new Promise((resolveExit) => {
|
|
40456
|
-
const proc =
|
|
40949
|
+
const proc = spawn3("npx", [
|
|
40457
40950
|
runner,
|
|
40458
40951
|
...args2
|
|
40459
40952
|
], {
|
|
@@ -40846,6 +41339,12 @@ async function sourceRollbackCommand(opts) {
|
|
|
40846
41339
|
const config = readYamlConfig();
|
|
40847
41340
|
const agentId = config?.agent?.agentId;
|
|
40848
41341
|
if (!agentId) throw new Error("No agentId in lua.skill.yaml. Run `lua init` first.");
|
|
41342
|
+
if (!opts.silent) {
|
|
41343
|
+
const versioning = await getVersioningModeCached(apiKey, agentId);
|
|
41344
|
+
if (versioning.enabled) {
|
|
41345
|
+
writeInfo("\u26A0\uFE0F `lua source rollback` is deprecated when agent versioning is on. Use `lua version promote <version>` \u2014 instant, no re-upload required.");
|
|
41346
|
+
}
|
|
41347
|
+
}
|
|
40849
41348
|
const fetchM = opts.fetchManifest ?? defaultFetchManifest;
|
|
40850
41349
|
const fetchU = opts.fetchUrls ?? defaultFetchUrls;
|
|
40851
41350
|
const dlBlobs = opts.downloadBlobs ?? downloadBlobsParallel;
|
|
@@ -40916,6 +41415,560 @@ function defaultRestore(manifest, blobs, targetDir) {
|
|
|
40916
41415
|
}
|
|
40917
41416
|
__name(defaultRestore, "defaultRestore");
|
|
40918
41417
|
|
|
41418
|
+
// src/commands/version.ts
|
|
41419
|
+
init_cli();
|
|
41420
|
+
init_command_utils();
|
|
41421
|
+
init_analytics();
|
|
41422
|
+
init_files();
|
|
41423
|
+
init_constants();
|
|
41424
|
+
|
|
41425
|
+
// src/utils/parse-version.ts
|
|
41426
|
+
function parseVersion2(arg) {
|
|
41427
|
+
if (!arg) throw new Error(`Invalid version "${arg}": must be a positive integer like "3" or "v3".`);
|
|
41428
|
+
const stripped = arg.replace(/^v/i, "");
|
|
41429
|
+
const n = Number.parseInt(stripped, 10);
|
|
41430
|
+
if (!Number.isFinite(n) || n <= 0 || String(n) !== stripped) {
|
|
41431
|
+
throw new Error(`Invalid version "${arg}": must be a positive integer like "3" or "v3".`);
|
|
41432
|
+
}
|
|
41433
|
+
return n;
|
|
41434
|
+
}
|
|
41435
|
+
__name(parseVersion2, "parseVersion");
|
|
41436
|
+
|
|
41437
|
+
// src/commands/version.ts
|
|
41438
|
+
async function assertVersioningEnabled(apiKey, agentId) {
|
|
41439
|
+
const { enabled } = await getVersioningModeCached(apiKey, agentId);
|
|
41440
|
+
if (!enabled) {
|
|
41441
|
+
throw new Error("Agent versioning is not enabled for your organization. Contact your admin to enable it, or use `lua push <primitive>` for the legacy flow.");
|
|
41442
|
+
}
|
|
41443
|
+
}
|
|
41444
|
+
__name(assertVersioningEnabled, "assertVersioningEnabled");
|
|
41445
|
+
async function versionCreateCommand(options = {}) {
|
|
41446
|
+
return withErrorHandling(async () => {
|
|
41447
|
+
const { apiKey, agentId } = await initializeCommand();
|
|
41448
|
+
await assertVersioningEnabled(apiKey, agentId);
|
|
41449
|
+
let config = readYamlConfig();
|
|
41450
|
+
let backupVersion = config?.backup?.activeVersion;
|
|
41451
|
+
if (options.autoPush) {
|
|
41452
|
+
await pushAllCommand({
|
|
41453
|
+
force: true,
|
|
41454
|
+
includeSource: true,
|
|
41455
|
+
suppressVersionCreateHint: true
|
|
41456
|
+
});
|
|
41457
|
+
config = readYamlConfig();
|
|
41458
|
+
backupVersion = config?.backup?.activeVersion;
|
|
41459
|
+
if (backupVersion == null) {
|
|
41460
|
+
throw new Error("Backup tracking lost after push. Aborting.");
|
|
41461
|
+
}
|
|
41462
|
+
}
|
|
41463
|
+
if (backupVersion == null) {
|
|
41464
|
+
throw new Error("No backup exists for this agent. Run `lua push` first, or pass `--auto-push` to push and snapshot in one step.");
|
|
41465
|
+
}
|
|
41466
|
+
let message = options.message;
|
|
41467
|
+
const isTTY = Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
41468
|
+
const isCi = isCiModeEnabled();
|
|
41469
|
+
if (!message && isTTY && !isCi) {
|
|
41470
|
+
const answers = await safePrompt([
|
|
41471
|
+
{
|
|
41472
|
+
type: "input",
|
|
41473
|
+
name: "input",
|
|
41474
|
+
message: "Optional description (blank to skip):"
|
|
41475
|
+
}
|
|
41476
|
+
]);
|
|
41477
|
+
message = answers?.input?.trim() || void 0;
|
|
41478
|
+
}
|
|
41479
|
+
const api = new AgentVersionApi(BASE_URLS.API, apiKey, agentId);
|
|
41480
|
+
const result = await api.createVersion({
|
|
41481
|
+
message,
|
|
41482
|
+
sourceManifestVersion: backupVersion,
|
|
41483
|
+
commitHash: options.commitHash
|
|
41484
|
+
});
|
|
41485
|
+
if (!result.success || !result.data) {
|
|
41486
|
+
throw new Error(result.error?.message ?? "Failed to create version");
|
|
41487
|
+
}
|
|
41488
|
+
writeInfo(`\u2713 Created v${result.data.version} (staged). Run \`lua version promote v${result.data.version}\` to deploy.`);
|
|
41489
|
+
try {
|
|
41490
|
+
const gitResult = await tryGitCommit({
|
|
41491
|
+
message: GIT_MESSAGES.createVersion(result.data.version, message),
|
|
41492
|
+
action: "version-create",
|
|
41493
|
+
tag: tagName(result.data.version),
|
|
41494
|
+
allowEmpty: true
|
|
41495
|
+
});
|
|
41496
|
+
if (gitResult.committed && gitResult.sha) {
|
|
41497
|
+
await api.patchCommitHash(result.data.version, gitResult.sha);
|
|
41498
|
+
}
|
|
41499
|
+
} catch {
|
|
41500
|
+
}
|
|
41501
|
+
trackEvent("cli_version_create_completed", {
|
|
41502
|
+
auto_push: Boolean(options.autoPush),
|
|
41503
|
+
has_message: Boolean(message),
|
|
41504
|
+
non_interactive: !isTTY || isCi
|
|
41505
|
+
});
|
|
41506
|
+
}, "version create");
|
|
41507
|
+
}
|
|
41508
|
+
__name(versionCreateCommand, "versionCreateCommand");
|
|
41509
|
+
async function versionListCommand(options = {}) {
|
|
41510
|
+
return withErrorHandling(async () => {
|
|
41511
|
+
const { apiKey, agentId } = await initializeCommand();
|
|
41512
|
+
await assertVersioningEnabled(apiKey, agentId);
|
|
41513
|
+
const query = {};
|
|
41514
|
+
if (options.all) query.all = true;
|
|
41515
|
+
if (options.limit != null) query.limit = options.limit;
|
|
41516
|
+
if (options.status) query.status = options.status;
|
|
41517
|
+
const api = new AgentVersionApi(BASE_URLS.API, apiKey, agentId);
|
|
41518
|
+
const response = await api.listVersions(query);
|
|
41519
|
+
if (!response.success || !response.data) {
|
|
41520
|
+
throw new Error(response.error?.message ?? "Failed to list versions");
|
|
41521
|
+
}
|
|
41522
|
+
const versions = response.data;
|
|
41523
|
+
if (options.json) {
|
|
41524
|
+
console.log(JSON.stringify(versions, null, 2));
|
|
41525
|
+
} else if (versions.length === 0) {
|
|
41526
|
+
writeInfo("(no versions yet \u2014 run `lua version create` to make one)");
|
|
41527
|
+
} else {
|
|
41528
|
+
console.log("VERSION STATUS CREATED BY MESSAGE");
|
|
41529
|
+
for (const v of versions) {
|
|
41530
|
+
const star = v.status === "active" ? "*" : " ";
|
|
41531
|
+
const date = new Date(v.createdAt).toISOString().slice(0, 16).replace("T", " ");
|
|
41532
|
+
const status = v.status.padEnd(11);
|
|
41533
|
+
const by = (v.createdBy || "").slice(0, 10).padEnd(10);
|
|
41534
|
+
const msg = (v.message || "").slice(0, 60);
|
|
41535
|
+
console.log(`v${v.version}${star} ${status} ${date} ${by}${msg}`);
|
|
41536
|
+
}
|
|
41537
|
+
}
|
|
41538
|
+
trackEvent("cli_version_list_completed", {
|
|
41539
|
+
count: versions.length,
|
|
41540
|
+
status_filter: options.status ?? "all"
|
|
41541
|
+
});
|
|
41542
|
+
}, "version list");
|
|
41543
|
+
}
|
|
41544
|
+
__name(versionListCommand, "versionListCommand");
|
|
41545
|
+
async function versionShowCommand(versionArg, options = {}) {
|
|
41546
|
+
return withErrorHandling(async () => {
|
|
41547
|
+
const { apiKey, agentId } = await initializeCommand();
|
|
41548
|
+
await assertVersioningEnabled(apiKey, agentId);
|
|
41549
|
+
const version = parseVersion2(versionArg);
|
|
41550
|
+
const api = new AgentVersionApi(BASE_URLS.API, apiKey, agentId);
|
|
41551
|
+
const response = await api.getVersion(version);
|
|
41552
|
+
if (!response.success || !response.data) {
|
|
41553
|
+
throw new Error(response.error?.message ?? `Version v${version} not found`);
|
|
41554
|
+
}
|
|
41555
|
+
const v = response.data;
|
|
41556
|
+
if (options.json) {
|
|
41557
|
+
console.log(JSON.stringify(v, null, 2));
|
|
41558
|
+
} else {
|
|
41559
|
+
console.log(`Version v${v.version} (${v.status})`);
|
|
41560
|
+
console.log(` Created: ${v.createdAt} by ${v.createdBy}`);
|
|
41561
|
+
if (v.message) console.log(` Message: ${v.message}`);
|
|
41562
|
+
if (v.commitHash) console.log(` Commit: ${v.commitHash}`);
|
|
41563
|
+
console.log(` Model: ${v.snapshot.model}`);
|
|
41564
|
+
console.log(` Snapshot:`);
|
|
41565
|
+
console.log(` Skills: ${v.snapshot.skills.length}`);
|
|
41566
|
+
console.log(` Webhooks: ${v.snapshot.webhooks.length}`);
|
|
41567
|
+
console.log(` Jobs: ${v.snapshot.jobs.length}`);
|
|
41568
|
+
console.log(` Preprocessors: ${v.snapshot.preprocessors.length}`);
|
|
41569
|
+
console.log(` Postprocessors: ${v.snapshot.postprocessors.length}`);
|
|
41570
|
+
console.log(` MCP servers: ${v.snapshot.mcpServers.length}`);
|
|
41571
|
+
console.log(` Persona: ${v.snapshot.persona.versionId || "(none)"}`);
|
|
41572
|
+
}
|
|
41573
|
+
trackEvent("cli_version_show_completed", {
|
|
41574
|
+
version,
|
|
41575
|
+
json: Boolean(options.json)
|
|
41576
|
+
});
|
|
41577
|
+
}, "version show");
|
|
41578
|
+
}
|
|
41579
|
+
__name(versionShowCommand, "versionShowCommand");
|
|
41580
|
+
async function versionDiffCommand(fromArg, toArg, options = {}) {
|
|
41581
|
+
return withErrorHandling(async () => {
|
|
41582
|
+
const { apiKey, agentId } = await initializeCommand();
|
|
41583
|
+
await assertVersioningEnabled(apiKey, agentId);
|
|
41584
|
+
const from = parseVersion2(fromArg);
|
|
41585
|
+
const to = parseVersion2(toArg);
|
|
41586
|
+
const api = new AgentVersionApi(BASE_URLS.API, apiKey, agentId);
|
|
41587
|
+
const response = await api.diffVersions(from, to);
|
|
41588
|
+
if (!response.success || !response.data) {
|
|
41589
|
+
throw new Error(response.error?.message ?? "Failed to diff versions");
|
|
41590
|
+
}
|
|
41591
|
+
const diff = response.data;
|
|
41592
|
+
if (options.json) {
|
|
41593
|
+
console.log(JSON.stringify(diff, null, 2));
|
|
41594
|
+
} else {
|
|
41595
|
+
console.log(`Diff v${from} \u2192 v${to}`);
|
|
41596
|
+
const sections = [
|
|
41597
|
+
{
|
|
41598
|
+
name: "Skills",
|
|
41599
|
+
entry: diff.skills,
|
|
41600
|
+
key: "skillId"
|
|
41601
|
+
},
|
|
41602
|
+
{
|
|
41603
|
+
name: "Webhooks",
|
|
41604
|
+
entry: diff.webhooks,
|
|
41605
|
+
key: "webhookId"
|
|
41606
|
+
},
|
|
41607
|
+
{
|
|
41608
|
+
name: "Jobs",
|
|
41609
|
+
entry: diff.jobs,
|
|
41610
|
+
key: "jobId"
|
|
41611
|
+
},
|
|
41612
|
+
{
|
|
41613
|
+
name: "Preprocessors",
|
|
41614
|
+
entry: diff.preprocessors,
|
|
41615
|
+
key: "id"
|
|
41616
|
+
},
|
|
41617
|
+
{
|
|
41618
|
+
name: "Postprocessors",
|
|
41619
|
+
entry: diff.postprocessors,
|
|
41620
|
+
key: "id"
|
|
41621
|
+
}
|
|
41622
|
+
];
|
|
41623
|
+
for (const { name, entry, key } of sections) {
|
|
41624
|
+
const total = entry.added.length + entry.removed.length + entry.changed.length;
|
|
41625
|
+
if (total === 0) {
|
|
41626
|
+
console.log(`${name}: (no changes)`);
|
|
41627
|
+
continue;
|
|
41628
|
+
}
|
|
41629
|
+
console.log(`${name}:`);
|
|
41630
|
+
for (const a of entry.added) {
|
|
41631
|
+
console.log(` + ${a[key]}@${a.version} (added)`);
|
|
41632
|
+
}
|
|
41633
|
+
for (const r of entry.removed) {
|
|
41634
|
+
console.log(` - ${r[key]}@${r.version} (removed)`);
|
|
41635
|
+
}
|
|
41636
|
+
for (const c of entry.changed) {
|
|
41637
|
+
console.log(` ~ ${c[key]} ${c.from.version} \u2192 ${c.to.version}`);
|
|
41638
|
+
}
|
|
41639
|
+
}
|
|
41640
|
+
const mcp = diff.mcpServers;
|
|
41641
|
+
if (mcp.added.length || mcp.removed.length || mcp.changed.length) {
|
|
41642
|
+
console.log("MCP servers:");
|
|
41643
|
+
mcp.added.forEach((m) => console.log(` + ${m.id} (added)`));
|
|
41644
|
+
mcp.removed.forEach((m) => console.log(` - ${m.id} (removed)`));
|
|
41645
|
+
mcp.changed.forEach((m) => console.log(` ~ ${m.id} (config changed)`));
|
|
41646
|
+
} else {
|
|
41647
|
+
console.log("MCP servers: (no changes)");
|
|
41648
|
+
}
|
|
41649
|
+
console.log(`Persona: ${diff.persona ? `${diff.persona.from} \u2192 ${diff.persona.to}` : "(unchanged)"}`);
|
|
41650
|
+
console.log(`Model: ${diff.model ? `${diff.model.from} \u2192 ${diff.model.to}` : "(unchanged)"}`);
|
|
41651
|
+
}
|
|
41652
|
+
trackEvent("cli_version_diff_completed", {
|
|
41653
|
+
from_to_distance: Math.abs(to - from)
|
|
41654
|
+
});
|
|
41655
|
+
}, "version diff");
|
|
41656
|
+
}
|
|
41657
|
+
__name(versionDiffCommand, "versionDiffCommand");
|
|
41658
|
+
async function versionPromoteCommand(versionArg) {
|
|
41659
|
+
return withErrorHandling(async () => {
|
|
41660
|
+
const { apiKey, agentId } = await initializeCommand();
|
|
41661
|
+
await assertVersioningEnabled(apiKey, agentId);
|
|
41662
|
+
const version = parseVersion2(versionArg);
|
|
41663
|
+
const api = new AgentVersionApi(BASE_URLS.API, apiKey, agentId);
|
|
41664
|
+
const response = await api.promoteVersion(version);
|
|
41665
|
+
if (!response.success) {
|
|
41666
|
+
const errCode = response.error?.code;
|
|
41667
|
+
if (errCode === "VERSION_ALREADY_ACTIVE") {
|
|
41668
|
+
writeInfo(`v${version} is already active. No change.`);
|
|
41669
|
+
return;
|
|
41670
|
+
}
|
|
41671
|
+
throw new Error(response.error?.message ?? `Failed to promote v${version}`);
|
|
41672
|
+
}
|
|
41673
|
+
if (!response.data) {
|
|
41674
|
+
throw new Error(`Promote returned no data`);
|
|
41675
|
+
}
|
|
41676
|
+
const { promoted, previousActive } = response.data;
|
|
41677
|
+
const rollback = previousActive != null && previousActive > promoted;
|
|
41678
|
+
if (previousActive == null) {
|
|
41679
|
+
writeInfo(`\u2713 Promoted v${promoted}. (No previous active version.)`);
|
|
41680
|
+
} else {
|
|
41681
|
+
writeInfo(`\u2713 Promoted v${promoted}. Previous active: v${previousActive}.`);
|
|
41682
|
+
}
|
|
41683
|
+
try {
|
|
41684
|
+
await tryGitCommit({
|
|
41685
|
+
message: GIT_MESSAGES.promote(promoted),
|
|
41686
|
+
action: "version-promote",
|
|
41687
|
+
allowEmpty: true
|
|
41688
|
+
});
|
|
41689
|
+
} catch {
|
|
41690
|
+
}
|
|
41691
|
+
trackEvent("cli_version_promote_completed", {
|
|
41692
|
+
from_version: previousActive,
|
|
41693
|
+
to_version: promoted,
|
|
41694
|
+
rollback
|
|
41695
|
+
});
|
|
41696
|
+
}, "version promote");
|
|
41697
|
+
}
|
|
41698
|
+
__name(versionPromoteCommand, "versionPromoteCommand");
|
|
41699
|
+
async function versionDeleteCommand(versionArg, options = {}) {
|
|
41700
|
+
return withErrorHandling(async () => {
|
|
41701
|
+
const { apiKey, agentId } = await initializeCommand();
|
|
41702
|
+
await assertVersioningEnabled(apiKey, agentId);
|
|
41703
|
+
if (versionArg === "current" || versionArg === "active") {
|
|
41704
|
+
throw new Error(`Cannot delete the active version directly. Use \`lua version promote <other>\` to roll back first, then delete.`);
|
|
41705
|
+
}
|
|
41706
|
+
const version = parseVersion2(versionArg);
|
|
41707
|
+
const isTTY = Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
41708
|
+
const isCi = isCiModeEnabled();
|
|
41709
|
+
if (!options.force && isTTY && !isCi) {
|
|
41710
|
+
const answer = await safePrompt([
|
|
41711
|
+
{
|
|
41712
|
+
type: "confirm",
|
|
41713
|
+
name: "confirm",
|
|
41714
|
+
message: `Delete v${version}?`,
|
|
41715
|
+
default: false
|
|
41716
|
+
}
|
|
41717
|
+
]);
|
|
41718
|
+
if (!answer?.confirm) {
|
|
41719
|
+
writeInfo("Aborted.");
|
|
41720
|
+
return;
|
|
41721
|
+
}
|
|
41722
|
+
}
|
|
41723
|
+
const api = new AgentVersionApi(BASE_URLS.API, apiKey, agentId);
|
|
41724
|
+
const response = await api.deleteVersion(version);
|
|
41725
|
+
if (!response.success) {
|
|
41726
|
+
const errCode = response.error?.code;
|
|
41727
|
+
if (errCode === "CANNOT_DELETE_ACTIVE_VERSION") {
|
|
41728
|
+
throw new Error(`Cannot delete v${version}: it is the active version. Promote a different version first.`);
|
|
41729
|
+
}
|
|
41730
|
+
if (errCode === "CANNOT_DELETE_LAST_VERSION") {
|
|
41731
|
+
throw new Error(`Cannot delete v${version}: it is the only remaining version.`);
|
|
41732
|
+
}
|
|
41733
|
+
throw new Error(response.error?.message ?? `Failed to delete v${version}`);
|
|
41734
|
+
}
|
|
41735
|
+
writeInfo(`\u2713 Deleted v${version}.`);
|
|
41736
|
+
try {
|
|
41737
|
+
await tryGitCommit({
|
|
41738
|
+
message: GIT_MESSAGES.delete(version),
|
|
41739
|
+
action: "version-delete",
|
|
41740
|
+
allowEmpty: true
|
|
41741
|
+
});
|
|
41742
|
+
} catch {
|
|
41743
|
+
}
|
|
41744
|
+
trackEvent("cli_version_delete_completed", {
|
|
41745
|
+
version,
|
|
41746
|
+
force: Boolean(options.force)
|
|
41747
|
+
});
|
|
41748
|
+
}, "version delete");
|
|
41749
|
+
}
|
|
41750
|
+
__name(versionDeleteCommand, "versionDeleteCommand");
|
|
41751
|
+
|
|
41752
|
+
// src/commands/git.ts
|
|
41753
|
+
init_cli();
|
|
41754
|
+
init_files();
|
|
41755
|
+
init_analytics();
|
|
41756
|
+
var NO_YAML_MESSAGE = "No lua.skill.yaml found. Please run this command from a skill directory.";
|
|
41757
|
+
function failConnect(status, banner, errorMessage) {
|
|
41758
|
+
if (banner) writeError(banner);
|
|
41759
|
+
trackEvent("cli_git_connect_completed", {
|
|
41760
|
+
...status,
|
|
41761
|
+
succeeded: false
|
|
41762
|
+
});
|
|
41763
|
+
throw new Error(errorMessage);
|
|
41764
|
+
}
|
|
41765
|
+
__name(failConnect, "failConnect");
|
|
41766
|
+
async function gitConnectCommand() {
|
|
41767
|
+
return withErrorHandling(async () => {
|
|
41768
|
+
const config = readYamlConfig();
|
|
41769
|
+
if (!config) {
|
|
41770
|
+
failConnect({
|
|
41771
|
+
git_available: false,
|
|
41772
|
+
in_repo: false,
|
|
41773
|
+
user_configured: false
|
|
41774
|
+
}, null, NO_YAML_MESSAGE);
|
|
41775
|
+
}
|
|
41776
|
+
if (!await isGitAvailable()) {
|
|
41777
|
+
failConnect({
|
|
41778
|
+
git_available: false,
|
|
41779
|
+
in_repo: false,
|
|
41780
|
+
user_configured: false
|
|
41781
|
+
}, "\u2717 Git binary not found on PATH.\n Fix: install git from https://git-scm.com/downloads, then re-run `lua git connect`.", "git is not installed");
|
|
41782
|
+
}
|
|
41783
|
+
if (!await isInsideGitRepo()) {
|
|
41784
|
+
failConnect({
|
|
41785
|
+
git_available: true,
|
|
41786
|
+
in_repo: false,
|
|
41787
|
+
user_configured: false
|
|
41788
|
+
}, "\u2717 This directory is not inside a git repository.\n Fix: run `git init` in your project root, then re-run `lua git connect`.", "not inside a git repository");
|
|
41789
|
+
}
|
|
41790
|
+
const identity = await gitUserConfigured();
|
|
41791
|
+
if (!identity.email) {
|
|
41792
|
+
failConnect({
|
|
41793
|
+
git_available: true,
|
|
41794
|
+
in_repo: true,
|
|
41795
|
+
user_configured: false
|
|
41796
|
+
}, '\u2717 Git user.email is not configured.\n Fix: git config --global user.email "you@example.com"', "git user.email is not configured");
|
|
41797
|
+
}
|
|
41798
|
+
if (!identity.name) {
|
|
41799
|
+
failConnect({
|
|
41800
|
+
git_available: true,
|
|
41801
|
+
in_repo: true,
|
|
41802
|
+
user_configured: false
|
|
41803
|
+
}, '\u2717 Git user.name is not configured.\n Fix: git config --global user.name "Your Name"', "git user.name is not configured");
|
|
41804
|
+
}
|
|
41805
|
+
config.git = {
|
|
41806
|
+
enabled: true
|
|
41807
|
+
};
|
|
41808
|
+
writeYamlConfig(config);
|
|
41809
|
+
writeSuccess("\u2713 Git integration enabled. Future `lua push`, `lua version *`, and `lua pull` runs will auto-commit.");
|
|
41810
|
+
trackEvent("cli_git_connect_completed", {
|
|
41811
|
+
git_available: true,
|
|
41812
|
+
in_repo: true,
|
|
41813
|
+
user_configured: true,
|
|
41814
|
+
succeeded: true
|
|
41815
|
+
});
|
|
41816
|
+
}, "git connect");
|
|
41817
|
+
}
|
|
41818
|
+
__name(gitConnectCommand, "gitConnectCommand");
|
|
41819
|
+
async function gitDisconnectCommand() {
|
|
41820
|
+
return withErrorHandling(async () => {
|
|
41821
|
+
const config = readYamlConfig();
|
|
41822
|
+
if (!config) {
|
|
41823
|
+
throw new Error(NO_YAML_MESSAGE);
|
|
41824
|
+
}
|
|
41825
|
+
config.git = {
|
|
41826
|
+
enabled: false
|
|
41827
|
+
};
|
|
41828
|
+
writeYamlConfig(config);
|
|
41829
|
+
writeSuccess("\u2713 Git integration disabled. Existing commits and tags are untouched.");
|
|
41830
|
+
trackEvent("cli_git_disconnect_completed", {});
|
|
41831
|
+
}, "git disconnect");
|
|
41832
|
+
}
|
|
41833
|
+
__name(gitDisconnectCommand, "gitDisconnectCommand");
|
|
41834
|
+
async function gitStatusCommand() {
|
|
41835
|
+
return withErrorHandling(async () => {
|
|
41836
|
+
const config = readYamlConfig();
|
|
41837
|
+
const enabled = Boolean(config?.git?.enabled);
|
|
41838
|
+
if (!enabled) {
|
|
41839
|
+
writeInfo("Git integration: disabled (run `lua git connect` to enable)");
|
|
41840
|
+
trackEvent("cli_git_status_completed", {
|
|
41841
|
+
enabled: false
|
|
41842
|
+
});
|
|
41843
|
+
return;
|
|
41844
|
+
}
|
|
41845
|
+
const settled = await Promise.allSettled([
|
|
41846
|
+
runGit([
|
|
41847
|
+
"--version"
|
|
41848
|
+
]),
|
|
41849
|
+
gitUserConfigured(),
|
|
41850
|
+
runGit([
|
|
41851
|
+
"log",
|
|
41852
|
+
"--grep",
|
|
41853
|
+
"^lua: ",
|
|
41854
|
+
"-n",
|
|
41855
|
+
"1",
|
|
41856
|
+
"--format=%h %s"
|
|
41857
|
+
]),
|
|
41858
|
+
// tryGitCommit creates lightweight tags (`git tag <name>`), which have
|
|
41859
|
+
// no taggerdate field. creatordate works for both flavors and returns
|
|
41860
|
+
// the committerdate of the referenced commit — chronological order
|
|
41861
|
+
// matches our pattern of tagging immediately after the commit.
|
|
41862
|
+
runGit([
|
|
41863
|
+
"for-each-ref",
|
|
41864
|
+
"--sort=-creatordate",
|
|
41865
|
+
"refs/tags/lua/",
|
|
41866
|
+
"--count=1",
|
|
41867
|
+
"--format=%(refname:short)"
|
|
41868
|
+
])
|
|
41869
|
+
]);
|
|
41870
|
+
const versionResult = settled[0].status === "fulfilled" ? settled[0].value : {
|
|
41871
|
+
stdout: "",
|
|
41872
|
+
stderr: "",
|
|
41873
|
+
code: 1
|
|
41874
|
+
};
|
|
41875
|
+
const identity = settled[1].status === "fulfilled" ? settled[1].value : {
|
|
41876
|
+
name: void 0,
|
|
41877
|
+
email: void 0
|
|
41878
|
+
};
|
|
41879
|
+
const lastCommitResult = settled[2].status === "fulfilled" ? settled[2].value : {
|
|
41880
|
+
stdout: "",
|
|
41881
|
+
stderr: "",
|
|
41882
|
+
code: 1
|
|
41883
|
+
};
|
|
41884
|
+
const lastTagResult = settled[3].status === "fulfilled" ? settled[3].value : {
|
|
41885
|
+
stdout: "",
|
|
41886
|
+
stderr: "",
|
|
41887
|
+
code: 1
|
|
41888
|
+
};
|
|
41889
|
+
const versionLine = versionResult.code === 0 ? `${versionResult.stdout.trim()} (\u2713)` : "(not detected)";
|
|
41890
|
+
const identityLine = identity.name && identity.email ? `${identity.name} <${identity.email}> (\u2713)` : "(not configured)";
|
|
41891
|
+
const lastCommit = lastCommitResult.code === 0 && lastCommitResult.stdout.trim() ? lastCommitResult.stdout.trim() : "(none yet)";
|
|
41892
|
+
const lastTag = lastTagResult.code === 0 && lastTagResult.stdout.trim() ? lastTagResult.stdout.trim() : "(none yet)";
|
|
41893
|
+
writeInfo(`Git integration: enabled`);
|
|
41894
|
+
writeInfo(`Project repo: ${process.cwd()}`);
|
|
41895
|
+
writeInfo(`Git binary: ${versionLine}`);
|
|
41896
|
+
writeInfo(`User identity: ${identityLine}`);
|
|
41897
|
+
writeInfo(`Last lua commit: ${lastCommit}`);
|
|
41898
|
+
writeInfo(`Last lua tag: ${lastTag}`);
|
|
41899
|
+
trackEvent("cli_git_status_completed", {
|
|
41900
|
+
enabled: true
|
|
41901
|
+
});
|
|
41902
|
+
}, "git status");
|
|
41903
|
+
}
|
|
41904
|
+
__name(gitStatusCommand, "gitStatusCommand");
|
|
41905
|
+
|
|
41906
|
+
// src/commands/pull.ts
|
|
41907
|
+
init_cli();
|
|
41908
|
+
init_command_utils();
|
|
41909
|
+
init_analytics();
|
|
41910
|
+
init_backup_api_service();
|
|
41911
|
+
init_constants();
|
|
41912
|
+
async function pullCommand(options = {}) {
|
|
41913
|
+
return withErrorHandling(async () => {
|
|
41914
|
+
const { apiKey, agentId } = await initializeCommand();
|
|
41915
|
+
const force = Boolean(options.force);
|
|
41916
|
+
if (options.version) {
|
|
41917
|
+
await assertVersioningEnabled(apiKey, agentId);
|
|
41918
|
+
const version = parseVersion2(options.version);
|
|
41919
|
+
const api = new AgentVersionApi(BASE_URLS.API, apiKey, agentId);
|
|
41920
|
+
const response = await api.getVersion(version);
|
|
41921
|
+
if (!response.success || !response.data) {
|
|
41922
|
+
throw new Error(response.error?.message ?? `Version v${version} not found`);
|
|
41923
|
+
}
|
|
41924
|
+
const sourceManifestVersion = response.data.sourceManifestVersion;
|
|
41925
|
+
if (sourceManifestVersion == null) {
|
|
41926
|
+
throw new Error(`Version v${version} has no source backup linked. Cannot pull source for this version.`);
|
|
41927
|
+
}
|
|
41928
|
+
writeInfo(`Pulling source for agent version v${version} (backup v${sourceManifestVersion})\u2026`);
|
|
41929
|
+
await sourceRollbackCommand({
|
|
41930
|
+
version: sourceManifestVersion,
|
|
41931
|
+
force,
|
|
41932
|
+
silent: true
|
|
41933
|
+
});
|
|
41934
|
+
try {
|
|
41935
|
+
await tryGitCommit({
|
|
41936
|
+
message: GIT_MESSAGES.pullVersion(version),
|
|
41937
|
+
action: "pull-version"
|
|
41938
|
+
});
|
|
41939
|
+
} catch {
|
|
41940
|
+
}
|
|
41941
|
+
trackEvent("cli_pull_completed", {
|
|
41942
|
+
has_version_arg: true
|
|
41943
|
+
});
|
|
41944
|
+
return;
|
|
41945
|
+
}
|
|
41946
|
+
const backupApi = new BackupApi(BASE_URLS.API, apiKey, agentId);
|
|
41947
|
+
const backupResp = await backupApi.getBackupVersions();
|
|
41948
|
+
if (!backupResp.success || !backupResp.data?.versions?.length) {
|
|
41949
|
+
throw new Error("No backup versions available to pull.");
|
|
41950
|
+
}
|
|
41951
|
+
const latest = backupResp.data.versions[0].version;
|
|
41952
|
+
writeInfo(`Pulling latest source backup (v${latest})\u2026`);
|
|
41953
|
+
await sourceRollbackCommand({
|
|
41954
|
+
version: latest,
|
|
41955
|
+
force,
|
|
41956
|
+
silent: true
|
|
41957
|
+
});
|
|
41958
|
+
try {
|
|
41959
|
+
await tryGitCommit({
|
|
41960
|
+
message: GIT_MESSAGES.pullLatest,
|
|
41961
|
+
action: "pull-latest"
|
|
41962
|
+
});
|
|
41963
|
+
} catch {
|
|
41964
|
+
}
|
|
41965
|
+
trackEvent("cli_pull_completed", {
|
|
41966
|
+
has_version_arg: false
|
|
41967
|
+
});
|
|
41968
|
+
}, "pull");
|
|
41969
|
+
}
|
|
41970
|
+
__name(pullCommand, "pullCommand");
|
|
41971
|
+
|
|
40919
41972
|
// src/cli/command-definitions.ts
|
|
40920
41973
|
init_cli();
|
|
40921
41974
|
function setupAuthCommands(program2) {
|
|
@@ -41544,6 +42597,50 @@ Examples:
|
|
|
41544
42597
|
$ lua voice test --runner vitest Force vitest
|
|
41545
42598
|
`).action(voiceTestCommand);
|
|
41546
42599
|
voice.command("list").description("List LuaVoice primitives in the compiled manifest").option("--json", "Output as JSON").action(voiceListCommand);
|
|
42600
|
+
const versionGroup = program2.command("version").description("\u{1F3F7}\uFE0F Manage agent versions (atomic snapshots of agent state)");
|
|
42601
|
+
versionGroup.command("create").description("Snapshot current staged state into a new version").option("-m, --message <message>", "Optional description for this version").option("--auto-push", "Push first if local changes are not yet staged").option("--commit-hash <hash>", "Optional git commit hash to associate with this version").addHelpText("after", `
|
|
42602
|
+
Examples:
|
|
42603
|
+
$ lua version create Snapshot current state
|
|
42604
|
+
$ lua version create -m "Add FAQ skill" Include a description
|
|
42605
|
+
$ lua version create --auto-push Push then snapshot in one step
|
|
42606
|
+
`).action((opts) => versionCreateCommand(opts));
|
|
42607
|
+
versionGroup.command("list").description("List versions of the current agent").option("--all", "Show all versions (no server-side cap)").option("--limit <n>", "Cap output to this many entries", (v) => parseInt(v, 10)).option("--status <status>", "Filter by status: active | staged | all", "all").option("--json", "Output as JSON").addHelpText("after", `
|
|
42608
|
+
Examples:
|
|
42609
|
+
$ lua version list List all versions (default)
|
|
42610
|
+
$ lua version list --status active Show only active versions
|
|
42611
|
+
$ lua version list --limit 10 Show the 10 most recent
|
|
42612
|
+
$ lua version list --json Machine-readable output
|
|
42613
|
+
`).action((opts) => versionListCommand(opts));
|
|
42614
|
+
versionGroup.command("show <version>").description("Show full snapshot of a specific version").option("--json", "Output as JSON").addHelpText("after", `
|
|
42615
|
+
Examples:
|
|
42616
|
+
$ lua version show 3 Show version 3 details
|
|
42617
|
+
$ lua version show v3 --json JSON output
|
|
42618
|
+
`).action((version, opts) => versionShowCommand(version, opts));
|
|
42619
|
+
versionGroup.command("diff <from> <to>").description("Compare two versions side-by-side").option("--json", "Output diff as JSON").addHelpText("after", `
|
|
42620
|
+
Examples:
|
|
42621
|
+
$ lua version diff 2 3 Compare v2 \u2192 v3
|
|
42622
|
+
$ lua version diff v2 v3 --json Machine-readable diff
|
|
42623
|
+
`).action((from, to, opts) => versionDiffCommand(from, to, opts));
|
|
42624
|
+
versionGroup.command("promote <version>").description("Promote a version to active (atomic, instant)").addHelpText("after", `
|
|
42625
|
+
Examples:
|
|
42626
|
+
$ lua version promote 3 Promote v3 to the active version
|
|
42627
|
+
$ lua version promote v3 Same (v-prefix accepted)
|
|
42628
|
+
`).action((version) => versionPromoteCommand(version));
|
|
42629
|
+
versionGroup.command("delete <version>").description("Soft-delete a version").option("--force", "Skip confirmation prompt").addHelpText("after", `
|
|
42630
|
+
Examples:
|
|
42631
|
+
$ lua version delete 3 Delete v3 (confirms first)
|
|
42632
|
+
$ lua version delete v3 --force Skip confirmation
|
|
42633
|
+
`).action((version, opts) => versionDeleteCommand(version, opts));
|
|
42634
|
+
const gitGroup = program2.command("git").description("Manage opt-in git auto-commits for this project");
|
|
42635
|
+
gitGroup.command("connect").description("Enable git auto-commits (runs sanity checks, writes git.enabled: true)").action(() => gitConnectCommand());
|
|
42636
|
+
gitGroup.command("disconnect").description("Disable git auto-commits (existing commits/tags untouched)").action(() => gitDisconnectCommand());
|
|
42637
|
+
gitGroup.command("status").description("Show git integration config + last lua-issued commit/tag").action(() => gitStatusCommand());
|
|
42638
|
+
program2.command("pull").description("\u{1F4E5} Pull the agent's source code locally").option("--version <version>", "Pull source linked to a specific agent version (requires versioning)").option("--force", "Skip confirmation prompt").addHelpText("after", `
|
|
42639
|
+
Examples:
|
|
42640
|
+
$ lua pull Restore the latest source backup
|
|
42641
|
+
$ lua pull --version 3 Restore the source snapshot from agent version 3
|
|
42642
|
+
$ lua pull --version v3 --force Skip the confirmation prompt
|
|
42643
|
+
`).action((opts) => pullCommand(opts));
|
|
41547
42644
|
const sourceCmd = program2.command("source").description("\u{1F5C2}\uFE0F Manage workspace source versions");
|
|
41548
42645
|
sourceCmd.command("list").description("List source versions for the current agent").option("--all", "Show all versions instead of the most recent 50", false).option("--limit <n>", "Number of versions to show", "50").addHelpText("after", `
|
|
41549
42646
|
Examples:
|