lua-cli 3.17.1 → 3.17.2
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 +8 -8
- package/dist/api-exports.js.map +1 -1
- package/dist/index.js +76 -193
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/template/lua.skill.yaml +10 -4
- package/template/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22224,6 +22224,23 @@ async function gitUserConfigured(cwd) {
|
|
|
22224
22224
|
};
|
|
22225
22225
|
}
|
|
22226
22226
|
__name(gitUserConfigured, "gitUserConfigured");
|
|
22227
|
+
async function getRemoteOriginUrl(cwd) {
|
|
22228
|
+
try {
|
|
22229
|
+
const { stdout, code } = await runGit([
|
|
22230
|
+
"config",
|
|
22231
|
+
"--get",
|
|
22232
|
+
"remote.origin.url"
|
|
22233
|
+
], {
|
|
22234
|
+
cwd
|
|
22235
|
+
});
|
|
22236
|
+
if (code !== 0) return null;
|
|
22237
|
+
const trimmed = stdout.trim();
|
|
22238
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
22239
|
+
} catch {
|
|
22240
|
+
return null;
|
|
22241
|
+
}
|
|
22242
|
+
}
|
|
22243
|
+
__name(getRemoteOriginUrl, "getRemoteOriginUrl");
|
|
22227
22244
|
async function getCommitSha(cwd) {
|
|
22228
22245
|
try {
|
|
22229
22246
|
const { stdout, code } = await runGit([
|
|
@@ -22305,39 +22322,17 @@ async function clearAuth(provider) {
|
|
|
22305
22322
|
__name(clearAuth, "clearAuth");
|
|
22306
22323
|
|
|
22307
22324
|
// src/utils/git-providers/github-provider.ts
|
|
22308
|
-
import { createServer } from "http";
|
|
22309
|
-
import { randomBytes as randomBytes2 } from "crypto";
|
|
22310
22325
|
import { request } from "undici";
|
|
22311
|
-
import open from "open";
|
|
22312
22326
|
|
|
22313
22327
|
// src/config/git-providers.constants.ts
|
|
22314
22328
|
var GITHUB_CLIENT_ID = "Ov23lipe1jgBlCsoi9OO";
|
|
22315
22329
|
var GITHUB_OAUTH_BASE_URL = "https://github.com";
|
|
22316
22330
|
var GITHUB_API_BASE_URL = "https://api.github.com";
|
|
22317
22331
|
var GITHUB_OAUTH_SCOPE = "repo";
|
|
22318
|
-
var LOOPBACK_PORT_MIN = 49152;
|
|
22319
|
-
var LOOPBACK_PORT_MAX = 65535;
|
|
22320
|
-
var LOOPBACK_PORT_ATTEMPTS = 3;
|
|
22321
|
-
var LOOPBACK_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
22322
22332
|
var DEVICE_FLOW_DEFAULT_INTERVAL_MS = 5e3;
|
|
22323
22333
|
var DEVICE_FLOW_SLOW_DOWN_INCREMENT_MS = 5e3;
|
|
22324
22334
|
var PUSH_TIMEOUT_MS = 2 * 60 * 1e3;
|
|
22325
22335
|
|
|
22326
|
-
// src/utils/pkce.ts
|
|
22327
|
-
import { createHash as createHash2, randomBytes } from "crypto";
|
|
22328
|
-
function generateCodeVerifier() {
|
|
22329
|
-
return base64url(randomBytes(64));
|
|
22330
|
-
}
|
|
22331
|
-
__name(generateCodeVerifier, "generateCodeVerifier");
|
|
22332
|
-
function computeCodeChallenge(verifier) {
|
|
22333
|
-
return base64url(createHash2("sha256").update(verifier).digest());
|
|
22334
|
-
}
|
|
22335
|
-
__name(computeCodeChallenge, "computeCodeChallenge");
|
|
22336
|
-
function base64url(buf) {
|
|
22337
|
-
return buf.toString("base64").replace(/=+$/, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
22338
|
-
}
|
|
22339
|
-
__name(base64url, "base64url");
|
|
22340
|
-
|
|
22341
22336
|
// src/interfaces/git-providers.ts
|
|
22342
22337
|
var GitPushError = class extends Error {
|
|
22343
22338
|
static {
|
|
@@ -22362,18 +22357,26 @@ function scrubToken(s, token) {
|
|
|
22362
22357
|
__name(scrubToken, "scrubToken");
|
|
22363
22358
|
|
|
22364
22359
|
// src/utils/git-providers/github-provider.ts
|
|
22365
|
-
var SUCCESS_HTML = `<!doctype html><meta charset="utf-8"><title>Lua CLI</title>
|
|
22366
|
-
<body style="font-family: system-ui; padding: 4rem; text-align: center;">
|
|
22367
|
-
<h1>✓ Connected</h1>
|
|
22368
|
-
<p>You can close this tab and return to the terminal.</p>
|
|
22369
|
-
</body>`;
|
|
22370
22360
|
var GitHubProvider = class {
|
|
22371
22361
|
static {
|
|
22372
22362
|
__name(this, "GitHubProvider");
|
|
22373
22363
|
}
|
|
22374
22364
|
name = "github";
|
|
22375
|
-
|
|
22376
|
-
|
|
22365
|
+
/**
|
|
22366
|
+
* GitHub is authenticated via the OAuth **device flow** only.
|
|
22367
|
+
*
|
|
22368
|
+
* The browser/loopback authorization-code flow is intentionally NOT used:
|
|
22369
|
+
* GitHub requires a `client_secret` to exchange the code (PKCE does not
|
|
22370
|
+
* replace it — the secretless exchange returns `incorrect_client_credentials`),
|
|
22371
|
+
* and a CLI published to npm cannot safely embed a secret. The device flow
|
|
22372
|
+
* needs no secret, which is why it is the only viable flow for a public
|
|
22373
|
+
* client (the same reason GitHub's own `gh` CLI defaults to it).
|
|
22374
|
+
*
|
|
22375
|
+
* `opts.device` is accepted for backwards compatibility but is now a no-op:
|
|
22376
|
+
* the device flow is always used.
|
|
22377
|
+
*/
|
|
22378
|
+
async login(_opts) {
|
|
22379
|
+
const token = await this.deviceFlow();
|
|
22377
22380
|
const username = await this.fetchUsername(token);
|
|
22378
22381
|
await saveAuth(this.name, {
|
|
22379
22382
|
token,
|
|
@@ -22416,126 +22419,6 @@ var GitHubProvider = class {
|
|
|
22416
22419
|
const status = matchPushStatus(scrubbed);
|
|
22417
22420
|
throw new GitPushError(status === 401 ? "GitHub authentication failed (token revoked or insufficient scope)." : status === 403 ? "GitHub rejected the push (403 \u2014 possible SSO enforcement or missing scope)." : "git push failed.", status, scrubbed);
|
|
22418
22421
|
}
|
|
22419
|
-
async loopbackFlow() {
|
|
22420
|
-
const verifier = generateCodeVerifier();
|
|
22421
|
-
const challenge = computeCodeChallenge(verifier);
|
|
22422
|
-
const state = randomBytes2(16).toString("hex");
|
|
22423
|
-
const { code, redirectUri } = await this.captureLoopbackCode({
|
|
22424
|
-
state,
|
|
22425
|
-
challenge
|
|
22426
|
-
});
|
|
22427
|
-
return this.exchangeCodeForToken({
|
|
22428
|
-
code,
|
|
22429
|
-
verifier,
|
|
22430
|
-
redirectUri
|
|
22431
|
-
});
|
|
22432
|
-
}
|
|
22433
|
-
async captureLoopbackCode(args2) {
|
|
22434
|
-
let lastErr;
|
|
22435
|
-
for (let i = 0; i < LOOPBACK_PORT_ATTEMPTS; i++) {
|
|
22436
|
-
const port = randomPort();
|
|
22437
|
-
try {
|
|
22438
|
-
return await this.runLoopbackServer(port, args2.state, args2.challenge);
|
|
22439
|
-
} catch (err) {
|
|
22440
|
-
lastErr = err;
|
|
22441
|
-
if (!isPortInUse(err)) throw err;
|
|
22442
|
-
}
|
|
22443
|
-
}
|
|
22444
|
-
throw new Error(`Could not bind a loopback port after ${LOOPBACK_PORT_ATTEMPTS} attempts. Try \`lua git auth github --device\` instead.${lastErr ? ` (${lastErr instanceof Error ? lastErr.message : String(lastErr)})` : ""}`);
|
|
22445
|
-
}
|
|
22446
|
-
runLoopbackServer(port, state, challenge) {
|
|
22447
|
-
return new Promise((resolveOuter, rejectOuter) => {
|
|
22448
|
-
let settled = false;
|
|
22449
|
-
const settle = /* @__PURE__ */ __name((fn) => {
|
|
22450
|
-
if (settled) return;
|
|
22451
|
-
settled = true;
|
|
22452
|
-
fn();
|
|
22453
|
-
}, "settle");
|
|
22454
|
-
const server = createServer((req, res) => {
|
|
22455
|
-
const url = new URL(req.url ?? "/", `http://127.0.0.1:${port}`);
|
|
22456
|
-
if (url.pathname !== "/callback") {
|
|
22457
|
-
res.writeHead(404).end();
|
|
22458
|
-
return;
|
|
22459
|
-
}
|
|
22460
|
-
const code = url.searchParams.get("code");
|
|
22461
|
-
const gotState = url.searchParams.get("state");
|
|
22462
|
-
if (!code || gotState !== state) {
|
|
22463
|
-
res.writeHead(400, {
|
|
22464
|
-
"content-type": "text/plain"
|
|
22465
|
-
}).end("State mismatch.");
|
|
22466
|
-
server.close();
|
|
22467
|
-
settle(() => {
|
|
22468
|
-
clearTimeout(timeout);
|
|
22469
|
-
rejectOuter(new Error("OAuth callback state mismatch (possible CSRF). Re-run the command."));
|
|
22470
|
-
});
|
|
22471
|
-
return;
|
|
22472
|
-
}
|
|
22473
|
-
res.writeHead(200, {
|
|
22474
|
-
"content-type": "text/html"
|
|
22475
|
-
}).end(SUCCESS_HTML);
|
|
22476
|
-
server.close();
|
|
22477
|
-
settle(() => {
|
|
22478
|
-
clearTimeout(timeout);
|
|
22479
|
-
resolveOuter({
|
|
22480
|
-
code,
|
|
22481
|
-
redirectUri
|
|
22482
|
-
});
|
|
22483
|
-
});
|
|
22484
|
-
});
|
|
22485
|
-
const timeout = setTimeout(() => {
|
|
22486
|
-
server.close();
|
|
22487
|
-
settle(() => rejectOuter(new Error("OAuth flow timed out (5 min). Re-run `lua git auth github`.")));
|
|
22488
|
-
}, LOOPBACK_TIMEOUT_MS);
|
|
22489
|
-
timeout.unref();
|
|
22490
|
-
server.on("error", (err) => {
|
|
22491
|
-
server.close();
|
|
22492
|
-
settle(() => {
|
|
22493
|
-
clearTimeout(timeout);
|
|
22494
|
-
rejectOuter(err);
|
|
22495
|
-
});
|
|
22496
|
-
});
|
|
22497
|
-
let redirectUri = "";
|
|
22498
|
-
server.listen(port, "127.0.0.1", () => {
|
|
22499
|
-
const actualPort = server.address().port;
|
|
22500
|
-
redirectUri = `http://127.0.0.1:${actualPort}/callback`;
|
|
22501
|
-
const authUrl = new URL(`${GITHUB_OAUTH_BASE_URL}/login/oauth/authorize`);
|
|
22502
|
-
authUrl.searchParams.set("client_id", GITHUB_CLIENT_ID);
|
|
22503
|
-
authUrl.searchParams.set("redirect_uri", redirectUri);
|
|
22504
|
-
authUrl.searchParams.set("scope", GITHUB_OAUTH_SCOPE);
|
|
22505
|
-
authUrl.searchParams.set("code_challenge", challenge);
|
|
22506
|
-
authUrl.searchParams.set("code_challenge_method", "S256");
|
|
22507
|
-
authUrl.searchParams.set("state", state);
|
|
22508
|
-
open(authUrl.toString()).catch(() => {
|
|
22509
|
-
server.close();
|
|
22510
|
-
settle(() => {
|
|
22511
|
-
clearTimeout(timeout);
|
|
22512
|
-
rejectOuter(new Error("Couldn't open a browser \u2014 try `lua git auth github --device` for the device flow."));
|
|
22513
|
-
});
|
|
22514
|
-
});
|
|
22515
|
-
});
|
|
22516
|
-
});
|
|
22517
|
-
}
|
|
22518
|
-
async exchangeCodeForToken(args2) {
|
|
22519
|
-
const res = await request(`${GITHUB_OAUTH_BASE_URL}/login/oauth/access_token`, {
|
|
22520
|
-
method: "POST",
|
|
22521
|
-
headers: {
|
|
22522
|
-
accept: "application/json",
|
|
22523
|
-
"content-type": "application/json"
|
|
22524
|
-
},
|
|
22525
|
-
body: JSON.stringify({
|
|
22526
|
-
client_id: GITHUB_CLIENT_ID,
|
|
22527
|
-
code: args2.code,
|
|
22528
|
-
code_verifier: args2.verifier,
|
|
22529
|
-
redirect_uri: args2.redirectUri,
|
|
22530
|
-
grant_type: "authorization_code"
|
|
22531
|
-
})
|
|
22532
|
-
});
|
|
22533
|
-
const body = await res.body.json();
|
|
22534
|
-
if (!body.access_token) {
|
|
22535
|
-
throw new Error(`GitHub rejected the token exchange: ${body.error ?? "unknown error"}`);
|
|
22536
|
-
}
|
|
22537
|
-
return body.access_token;
|
|
22538
|
-
}
|
|
22539
22422
|
async fetchUsername(token) {
|
|
22540
22423
|
const res = await request(`${GITHUB_API_BASE_URL}/user`, {
|
|
22541
22424
|
method: "GET",
|
|
@@ -22598,15 +22481,6 @@ var GitHubProvider = class {
|
|
|
22598
22481
|
throw new Error("Device flow timed out. Re-run `lua git auth github --device`.");
|
|
22599
22482
|
}
|
|
22600
22483
|
};
|
|
22601
|
-
function randomPort() {
|
|
22602
|
-
const span = LOOPBACK_PORT_MAX - LOOPBACK_PORT_MIN + 1;
|
|
22603
|
-
return LOOPBACK_PORT_MIN + Math.floor(Math.random() * span);
|
|
22604
|
-
}
|
|
22605
|
-
__name(randomPort, "randomPort");
|
|
22606
|
-
function isPortInUse(err) {
|
|
22607
|
-
return !!err && typeof err === "object" && "code" in err && err.code === "EADDRINUSE";
|
|
22608
|
-
}
|
|
22609
|
-
__name(isPortInUse, "isPortInUse");
|
|
22610
22484
|
function sleep(ms) {
|
|
22611
22485
|
return new Promise((r) => setTimeout(r, ms));
|
|
22612
22486
|
}
|
|
@@ -22665,7 +22539,7 @@ async function tryGitAutoPush(ctx) {
|
|
|
22665
22539
|
warnOnce("missing-github-token", "git.autoPush is enabled but no GitHub auth \u2014 run `lua git auth github`.");
|
|
22666
22540
|
return;
|
|
22667
22541
|
}
|
|
22668
|
-
const remote = await
|
|
22542
|
+
const remote = await getRemoteOriginUrl(ctx.cwd);
|
|
22669
22543
|
if (!remote) {
|
|
22670
22544
|
warnOnce("missing-github-remote", "git.autoPush is enabled but no `remote.origin.url` is set. Skipping push.");
|
|
22671
22545
|
return;
|
|
@@ -22715,19 +22589,6 @@ async function tryGitAutoPush(ctx) {
|
|
|
22715
22589
|
}
|
|
22716
22590
|
}
|
|
22717
22591
|
__name(tryGitAutoPush, "tryGitAutoPush");
|
|
22718
|
-
async function readRemoteOriginUrl(cwd) {
|
|
22719
|
-
const res = await runGit([
|
|
22720
|
-
"config",
|
|
22721
|
-
"--get",
|
|
22722
|
-
"remote.origin.url"
|
|
22723
|
-
], {
|
|
22724
|
-
cwd
|
|
22725
|
-
});
|
|
22726
|
-
if (res.code !== 0) return null;
|
|
22727
|
-
const trimmed = res.stdout.trim();
|
|
22728
|
-
return trimmed.length > 0 ? trimmed : null;
|
|
22729
|
-
}
|
|
22730
|
-
__name(readRemoteOriginUrl, "readRemoteOriginUrl");
|
|
22731
22592
|
async function readCurrentBranch(cwd) {
|
|
22732
22593
|
const res = await runGit([
|
|
22733
22594
|
"rev-parse",
|
|
@@ -28204,7 +28065,7 @@ __name(viewResourceInteractive, "viewResourceInteractive");
|
|
|
28204
28065
|
init_cli();
|
|
28205
28066
|
init_command_utils();
|
|
28206
28067
|
init_analytics();
|
|
28207
|
-
import
|
|
28068
|
+
import open from "open";
|
|
28208
28069
|
async function adminCommand() {
|
|
28209
28070
|
return withErrorHandling(async () => {
|
|
28210
28071
|
writeProgress("Opening Lua Admin Dashboard...");
|
|
@@ -28212,7 +28073,7 @@ async function adminCommand() {
|
|
|
28212
28073
|
showProgress: false
|
|
28213
28074
|
});
|
|
28214
28075
|
const adminUrl = `https://admin.heylua.ai/validate-token/${apiKey}?redirect=/admin/usage?&agentId=${agentId}&orgId=${orgId}`;
|
|
28215
|
-
await
|
|
28076
|
+
await open(adminUrl);
|
|
28216
28077
|
writeSuccess("Lua Admin Dashboard opened in your browser");
|
|
28217
28078
|
console.log(`
|
|
28218
28079
|
Dashboard URL: https://admin.heylua.ai`);
|
|
@@ -28228,7 +28089,7 @@ __name(adminCommand, "adminCommand");
|
|
|
28228
28089
|
init_cli();
|
|
28229
28090
|
init_command_utils();
|
|
28230
28091
|
init_analytics();
|
|
28231
|
-
import
|
|
28092
|
+
import open2 from "open";
|
|
28232
28093
|
async function evalsCommand() {
|
|
28233
28094
|
return withErrorHandling(async () => {
|
|
28234
28095
|
writeProgress("Opening Lua Evaluations Dashboard...");
|
|
@@ -28236,7 +28097,7 @@ async function evalsCommand() {
|
|
|
28236
28097
|
showProgress: false
|
|
28237
28098
|
});
|
|
28238
28099
|
const evalsUrl = `https://evals.heylua.ai?apiKey=${apiKey}&agentID=${agentId}`;
|
|
28239
|
-
await
|
|
28100
|
+
await open2(evalsUrl);
|
|
28240
28101
|
writeSuccess("Lua Evaluations Dashboard opened in your browser");
|
|
28241
28102
|
console.log(`
|
|
28242
28103
|
Dashboard URL: https://evals.heylua.ai`);
|
|
@@ -28250,12 +28111,12 @@ __name(evalsCommand, "evalsCommand");
|
|
|
28250
28111
|
// src/commands/docs.ts
|
|
28251
28112
|
init_cli();
|
|
28252
28113
|
init_analytics();
|
|
28253
|
-
import
|
|
28114
|
+
import open3 from "open";
|
|
28254
28115
|
async function docsCommand() {
|
|
28255
28116
|
return withErrorHandling(async () => {
|
|
28256
28117
|
writeProgress("Opening Lua Documentation...");
|
|
28257
28118
|
const docsUrl = "https://docs.heylua.ai";
|
|
28258
|
-
await
|
|
28119
|
+
await open3(docsUrl);
|
|
28259
28120
|
writeSuccess("Lua Documentation opened in your browser");
|
|
28260
28121
|
console.log(`
|
|
28261
28122
|
Documentation: ${docsUrl}
|
|
@@ -28269,7 +28130,7 @@ __name(docsCommand, "docsCommand");
|
|
|
28269
28130
|
init_cli();
|
|
28270
28131
|
init_command_utils();
|
|
28271
28132
|
import inquirer12 from "inquirer";
|
|
28272
|
-
import
|
|
28133
|
+
import open4 from "open";
|
|
28273
28134
|
|
|
28274
28135
|
// src/api/channels.api.service.ts
|
|
28275
28136
|
init_http_client();
|
|
@@ -28838,7 +28699,7 @@ async function openAdminDashboard(apiKey, config) {
|
|
|
28838
28699
|
throw new Error("No orgId found in lua.skill.yaml. Please ensure your configuration is valid.");
|
|
28839
28700
|
}
|
|
28840
28701
|
const adminUrl = `https://admin.heylua.ai/validate-token/${apiKey}?redirect=/admin/usage?&agentId=${agentId}&orgId=${orgId}`;
|
|
28841
|
-
await
|
|
28702
|
+
await open4(adminUrl);
|
|
28842
28703
|
writeSuccess("\u2705 Lua Admin Dashboard opened in your browser");
|
|
28843
28704
|
console.log(`
|
|
28844
28705
|
Dashboard URL: https://admin.heylua.ai`);
|
|
@@ -37622,7 +37483,7 @@ init_cli();
|
|
|
37622
37483
|
init_constants();
|
|
37623
37484
|
import http from "http";
|
|
37624
37485
|
import { URL as URL2 } from "url";
|
|
37625
|
-
import
|
|
37486
|
+
import open5 from "open";
|
|
37626
37487
|
init_command_utils();
|
|
37627
37488
|
init_developer_api_service();
|
|
37628
37489
|
|
|
@@ -38645,7 +38506,7 @@ Integration: ${selectedIntegration.name}`);
|
|
|
38645
38506
|
`);
|
|
38646
38507
|
const callbackPromise = startCallbackServer(3e5);
|
|
38647
38508
|
try {
|
|
38648
|
-
await
|
|
38509
|
+
await open5(authUrl);
|
|
38649
38510
|
writeInfo("\u{1F310} Browser opened - please complete the authorization");
|
|
38650
38511
|
} catch (error) {
|
|
38651
38512
|
writeInfo("\u{1F4A1} Could not open browser automatically. Please open the URL above manually.");
|
|
@@ -39076,7 +38937,7 @@ Available scopes for ${selectedIntegration.name}:`);
|
|
|
39076
38937
|
`);
|
|
39077
38938
|
const callbackPromise = startCallbackServer(3e5);
|
|
39078
38939
|
try {
|
|
39079
|
-
await
|
|
38940
|
+
await open5(authUrl);
|
|
39080
38941
|
writeInfo("\u{1F310} Browser opened - please complete the authorization");
|
|
39081
38942
|
} catch (error) {
|
|
39082
38943
|
writeInfo("\u{1F4A1} Could not open browser automatically. Please open the URL above manually.");
|
|
@@ -41289,7 +41150,7 @@ __name(pumpRemoteAudioToSpeaker, "pumpRemoteAudioToSpeaker");
|
|
|
41289
41150
|
// src/commands/voice-browser.ts
|
|
41290
41151
|
init_cli();
|
|
41291
41152
|
import http2 from "http";
|
|
41292
|
-
import
|
|
41153
|
+
import open6 from "open";
|
|
41293
41154
|
var SAFETY_TIMEOUT_MS = 60 * 60 * 1e3;
|
|
41294
41155
|
async function runBrowserMode(joinUrl) {
|
|
41295
41156
|
const { wsUrl, token } = parseJoinUrl(joinUrl);
|
|
@@ -41321,7 +41182,7 @@ async function runBrowserMode(joinUrl) {
|
|
|
41321
41182
|
const localUrl = `http://localhost:${port}/`;
|
|
41322
41183
|
writeSuccess(`Voice room ready (opening browser)`);
|
|
41323
41184
|
console.log(` ${localUrl}`);
|
|
41324
|
-
await
|
|
41185
|
+
await open6(localUrl);
|
|
41325
41186
|
await new Promise((resolve6) => {
|
|
41326
41187
|
const safety = setTimeout(() => {
|
|
41327
41188
|
try {
|
|
@@ -42374,7 +42235,7 @@ function failConnect(status, banner, errorMessage) {
|
|
|
42374
42235
|
throw new Error(errorMessage);
|
|
42375
42236
|
}
|
|
42376
42237
|
__name(failConnect, "failConnect");
|
|
42377
|
-
async function gitConnectCommand() {
|
|
42238
|
+
async function gitConnectCommand(opts = {}) {
|
|
42378
42239
|
return withErrorHandling(async () => {
|
|
42379
42240
|
const config = readYamlConfig();
|
|
42380
42241
|
if (!config) {
|
|
@@ -42413,15 +42274,35 @@ async function gitConnectCommand() {
|
|
|
42413
42274
|
user_configured: false
|
|
42414
42275
|
}, '\u2717 Git user.name is not configured.\n Fix: git config --global user.name "Your Name"', "git user.name is not configured");
|
|
42415
42276
|
}
|
|
42277
|
+
const passedStatus = {
|
|
42278
|
+
git_available: true,
|
|
42279
|
+
in_repo: true,
|
|
42280
|
+
user_configured: true
|
|
42281
|
+
};
|
|
42282
|
+
if (opts.autoPush) {
|
|
42283
|
+
const token = await getToken2("github");
|
|
42284
|
+
if (!token) {
|
|
42285
|
+
failConnect(passedStatus, "\u2717 --auto-push needs a linked GitHub account.\n Fix: run `lua git auth github` to link your GitHub account, then re-run `lua git connect --auto-push`.", "no GitHub account linked");
|
|
42286
|
+
}
|
|
42287
|
+
const remote = await getRemoteOriginUrl();
|
|
42288
|
+
if (!remote) {
|
|
42289
|
+
failConnect(passedStatus, "\u2717 --auto-push needs a GitHub remote, but `remote.origin.url` is not set.\n Fix: git remote add origin https://github.com/<owner>/<repo>.git", "no origin remote configured");
|
|
42290
|
+
}
|
|
42291
|
+
if (!isGitHubUrl(remote)) {
|
|
42292
|
+
failConnect(passedStatus, `\u2717 --auto-push only supports GitHub HTTPS remotes, but origin is ${remote}.
|
|
42293
|
+
Fix: git remote set-url origin https://github.com/<owner>/<repo>.git`, "origin is not a GitHub HTTPS remote");
|
|
42294
|
+
}
|
|
42295
|
+
}
|
|
42416
42296
|
config.git = {
|
|
42297
|
+
...config.git,
|
|
42417
42298
|
enabled: true
|
|
42418
42299
|
};
|
|
42300
|
+
if (opts.autoPush) config.git.autoPush = true;
|
|
42419
42301
|
writeYamlConfig(config);
|
|
42420
|
-
writeSuccess("\u2713 Git integration enabled. Future `lua push`, `lua version *`, and `lua pull` runs will auto-commit.");
|
|
42302
|
+
writeSuccess(opts.autoPush ? "\u2713 Git integration enabled with auto-push. Future `lua push`, `lua version *`, and `lua pull` runs will auto-commit and push to GitHub." : "\u2713 Git integration enabled. Future `lua push`, `lua version *`, and `lua pull` runs will auto-commit.");
|
|
42421
42303
|
trackEvent("cli_git_connect_completed", {
|
|
42422
|
-
|
|
42423
|
-
|
|
42424
|
-
user_configured: true,
|
|
42304
|
+
...passedStatus,
|
|
42305
|
+
auto_push: Boolean(opts.autoPush),
|
|
42425
42306
|
succeeded: true
|
|
42426
42307
|
});
|
|
42427
42308
|
}, "git connect");
|
|
@@ -42535,7 +42416,7 @@ function gitAuthGithubCommand(opts) {
|
|
|
42535
42416
|
writeSuccess(`Logged in to GitHub as @${result.username}.`);
|
|
42536
42417
|
trackEvent("cli_git_auth_succeeded", {
|
|
42537
42418
|
provider: "github",
|
|
42538
|
-
flow:
|
|
42419
|
+
flow: "device"
|
|
42539
42420
|
});
|
|
42540
42421
|
}, "git-auth-github");
|
|
42541
42422
|
}
|
|
@@ -43319,11 +43200,13 @@ Examples:
|
|
|
43319
43200
|
$ lua version delete v3 --force Skip confirmation
|
|
43320
43201
|
`).action((version, opts) => versionDeleteCommand(version, opts));
|
|
43321
43202
|
const gitGroup = program2.command("git").description("Manage opt-in git auto-commits for this project");
|
|
43322
|
-
gitGroup.command("connect").description("Enable git auto-commits (runs sanity checks, writes git.enabled: true)").action(() => gitConnectCommand(
|
|
43203
|
+
gitGroup.command("connect").description("Enable git auto-commits (runs sanity checks, writes git.enabled: true)").option("--auto-push", "Also enable post-commit auto-push (requires `lua git auth github` + a GitHub HTTPS origin remote)").action((opts) => gitConnectCommand({
|
|
43204
|
+
autoPush: opts.autoPush
|
|
43205
|
+
}));
|
|
43323
43206
|
gitGroup.command("disconnect").description("Disable git auto-commits (existing commits/tags untouched)").action(() => gitDisconnectCommand());
|
|
43324
43207
|
gitGroup.command("status").description("Show git integration config + last lua-issued commit/tag").action(() => gitStatusCommand());
|
|
43325
43208
|
const gitAuthGroup = gitGroup.command("auth").description("Manage git remote provider authentication");
|
|
43326
|
-
gitAuthGroup.command("github").description("Link a GitHub account").option("--device", "
|
|
43209
|
+
gitAuthGroup.command("github").description("Link a GitHub account (OAuth device flow)").option("--device", "(deprecated; device flow is always used \u2014 flag kept for compatibility)").option("--force", "Overwrite an existing link without prompting").action((opts) => gitAuthGithubCommand(opts));
|
|
43327
43210
|
gitAuthGroup.command("status").description("Show the current git auth status").action(() => gitAuthStatusCommand());
|
|
43328
43211
|
gitAuthGroup.command("disconnect [provider]").description("Disconnect a git provider (default: github)").action((provider) => gitAuthDisconnectCommand(provider));
|
|
43329
43212
|
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", `
|