lua-cli 3.17.0 → 3.17.1
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 +61 -0
- package/dist/api-exports.js +50 -2
- package/dist/api-exports.js.map +1 -1
- package/dist/index.js +730 -39
- package/dist/index.js.map +1 -1
- package/dist/voice/test/index.d.ts +20 -0
- package/package.json +3 -3
- package/template/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -132,7 +132,7 @@ 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, CLI_CACHE_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, AUTH_STORAGE_FILE, POSTHOG_API_KEY, POSTHOG_HOST;
|
|
136
136
|
var init_constants = __esm({
|
|
137
137
|
"src/config/constants.ts"() {
|
|
138
138
|
"use strict";
|
|
@@ -154,6 +154,7 @@ var init_constants = __esm({
|
|
|
154
154
|
"base"
|
|
155
155
|
];
|
|
156
156
|
SANDBOX_STORAGE_FILE = join(CLI_CONFIG_DIR, "sandbox.json");
|
|
157
|
+
AUTH_STORAGE_FILE = join(CLI_CONFIG_DIR, "auth.json");
|
|
157
158
|
POSTHOG_API_KEY = "phc_W7Qsquwlflshmdkm2hWSqRpXuxGbVFo7LEX8H9HrSjC";
|
|
158
159
|
POSTHOG_HOST = "https://us.i.posthog.com";
|
|
159
160
|
}
|
|
@@ -1199,7 +1200,14 @@ Feel free to add, remove, or rename sections. Your persona can be a single parag
|
|
|
1199
1200
|
// `Data.get('call:<sessionId>')` to drive post-call analytics, follow-ups,
|
|
1200
1201
|
// or QA workflows. Defaults to false — most calls don't need to keep
|
|
1201
1202
|
// a transcript copy.
|
|
1202
|
-
persistTranscript: z.boolean().optional()
|
|
1203
|
+
persistTranscript: z.boolean().optional(),
|
|
1204
|
+
// Spoken acknowledgement played when a tool call fails. When a tool
|
|
1205
|
+
// throws, times out, or returns an unsupported result, the adapter calls
|
|
1206
|
+
// `session.say(text)` once per failed call before surfacing the error
|
|
1207
|
+
// to the LLM as a ToolError — fills the 2–3s gap before the LLM's own
|
|
1208
|
+
// recovery response. Persona-specific (keep it short and on-brand);
|
|
1209
|
+
// absent → no spoken fallback (the LLM's recovery is the only signal).
|
|
1210
|
+
onToolFailureSay: z.string().min(1).max(200).optional()
|
|
1203
1211
|
});
|
|
1204
1212
|
LuaVoiceConfigSchema = LuaVoiceConfigInnerSchema.superRefine((cfg, ctx) => {
|
|
1205
1213
|
const isRealtime = cfg.llm.kind === "realtime";
|
|
@@ -6677,6 +6685,31 @@ var init_skill_plugin = __esm({
|
|
|
6677
6685
|
|
|
6678
6686
|
// src/compiler/plugins/agent.plugin.ts
|
|
6679
6687
|
import { Node as Node12 } from "ts-morph";
|
|
6688
|
+
function shapeModelSettings(raw) {
|
|
6689
|
+
const KNOWN_KEYS = [
|
|
6690
|
+
"temperature",
|
|
6691
|
+
"topP",
|
|
6692
|
+
"topK",
|
|
6693
|
+
"maxOutputTokens",
|
|
6694
|
+
"presencePenalty",
|
|
6695
|
+
"frequencyPenalty",
|
|
6696
|
+
"stopSequences",
|
|
6697
|
+
"seed"
|
|
6698
|
+
];
|
|
6699
|
+
const result = {};
|
|
6700
|
+
for (const key of KNOWN_KEYS) {
|
|
6701
|
+
const value = raw[key];
|
|
6702
|
+
if (value === void 0) continue;
|
|
6703
|
+
if (key === "stopSequences") {
|
|
6704
|
+
if (Array.isArray(value) && value.every((v) => typeof v === "string")) {
|
|
6705
|
+
result[key] = value;
|
|
6706
|
+
}
|
|
6707
|
+
} else if (typeof value === "number" && Number.isFinite(value)) {
|
|
6708
|
+
result[key] = value;
|
|
6709
|
+
}
|
|
6710
|
+
}
|
|
6711
|
+
return Object.keys(result).length > 0 ? result : void 0;
|
|
6712
|
+
}
|
|
6680
6713
|
var AgentPlugin, agentPlugin;
|
|
6681
6714
|
var init_agent_plugin = __esm({
|
|
6682
6715
|
"src/compiler/plugins/agent.plugin.ts"() {
|
|
@@ -6709,7 +6742,8 @@ var init_agent_plugin = __esm({
|
|
|
6709
6742
|
"name",
|
|
6710
6743
|
"description",
|
|
6711
6744
|
"persona",
|
|
6712
|
-
"model"
|
|
6745
|
+
"model",
|
|
6746
|
+
"modelSettings"
|
|
6713
6747
|
]
|
|
6714
6748
|
};
|
|
6715
6749
|
supportsClassDefinition = true;
|
|
@@ -6766,6 +6800,9 @@ var init_agent_plugin = __esm({
|
|
|
6766
6800
|
const governanceHit = findClassMember(classDecl, "governance", "property");
|
|
6767
6801
|
const governanceObj = governanceHit && Node12.isPropertyDeclaration(governanceHit.node) ? evaluateNodeAsObject(governanceHit.node.getInitializer()) : void 0;
|
|
6768
6802
|
const governance = governanceObj && typeof governanceObj.mode === "string" ? governanceObj : void 0;
|
|
6803
|
+
const modelSettingsHit = findClassMember(classDecl, "modelSettings", "property");
|
|
6804
|
+
const modelSettingsObj = modelSettingsHit && Node12.isPropertyDeclaration(modelSettingsHit.node) ? evaluateNodeAsObject(modelSettingsHit.node.getInitializer()) : void 0;
|
|
6805
|
+
const modelSettings = modelSettingsObj ? shapeModelSettings(modelSettingsObj) : void 0;
|
|
6769
6806
|
return {
|
|
6770
6807
|
kind: this.kind,
|
|
6771
6808
|
name,
|
|
@@ -6780,6 +6817,7 @@ var init_agent_plugin = __esm({
|
|
|
6780
6817
|
persona,
|
|
6781
6818
|
model,
|
|
6782
6819
|
hasModelResolver,
|
|
6820
|
+
modelSettings,
|
|
6783
6821
|
batching,
|
|
6784
6822
|
governance
|
|
6785
6823
|
}
|
|
@@ -6809,6 +6847,7 @@ var init_agent_plugin = __esm({
|
|
|
6809
6847
|
"text"
|
|
6810
6848
|
]) ?? "";
|
|
6811
6849
|
const { model, hasModelResolver } = this.extractModelInfo(config);
|
|
6850
|
+
const modelSettings = this.extractModelSettings(config);
|
|
6812
6851
|
const batching = this.extractBatchingInfo(config);
|
|
6813
6852
|
const governance = this.extractGovernanceInfo(config);
|
|
6814
6853
|
const { voiceRefNames, voiceRefSourcePaths } = this.extractVoiceRefs(config);
|
|
@@ -6825,6 +6864,7 @@ var init_agent_plugin = __esm({
|
|
|
6825
6864
|
persona,
|
|
6826
6865
|
model,
|
|
6827
6866
|
hasModelResolver,
|
|
6867
|
+
modelSettings,
|
|
6828
6868
|
batching,
|
|
6829
6869
|
governance,
|
|
6830
6870
|
voiceRefNames,
|
|
@@ -6895,6 +6935,17 @@ var init_agent_plugin = __esm({
|
|
|
6895
6935
|
return governance;
|
|
6896
6936
|
}
|
|
6897
6937
|
/**
|
|
6938
|
+
* Extract `modelSettings` from the config-literal path. Delegates to the
|
|
6939
|
+
* shared `shapeModelSettings` helper so the class-definition extraction
|
|
6940
|
+
* path applies the exact same key whitelist + type narrowing — without
|
|
6941
|
+
* the shared helper, the two paths would drift (see Bugbot #ref1).
|
|
6942
|
+
*/
|
|
6943
|
+
extractModelSettings(config) {
|
|
6944
|
+
const raw = extractObjectProperty(config, "modelSettings");
|
|
6945
|
+
if (!raw || typeof raw !== "object") return void 0;
|
|
6946
|
+
return shapeModelSettings(raw);
|
|
6947
|
+
}
|
|
6948
|
+
/**
|
|
6898
6949
|
* Extract model info from agent config.
|
|
6899
6950
|
* Returns the static model string (if any) and whether a resolver function exists.
|
|
6900
6951
|
*/
|
|
@@ -6976,6 +7027,7 @@ var init_agent_plugin = __esm({
|
|
|
6976
7027
|
persona: agentMeta.persona,
|
|
6977
7028
|
model: agentMeta.model,
|
|
6978
7029
|
hasModelResolver: agentMeta.hasModelResolver || void 0,
|
|
7030
|
+
modelSettings: agentMeta.modelSettings,
|
|
6979
7031
|
batching: agentMeta.batching,
|
|
6980
7032
|
governance: agentMeta.governance,
|
|
6981
7033
|
voiceRefs
|
|
@@ -7037,6 +7089,7 @@ var init_agent_plugin = __esm({
|
|
|
7037
7089
|
return rest;
|
|
7038
7090
|
}
|
|
7039
7091
|
};
|
|
7092
|
+
__name(shapeModelSettings, "shapeModelSettings");
|
|
7040
7093
|
agentPlugin = new AgentPlugin();
|
|
7041
7094
|
}
|
|
7042
7095
|
});
|
|
@@ -8100,6 +8153,7 @@ var init_voice_plugin = __esm({
|
|
|
8100
8153
|
const tts = extractModelField(config, "tts");
|
|
8101
8154
|
const krispEnabled = extractBooleanProperty(config, "krispEnabled");
|
|
8102
8155
|
const persistTranscript = extractBooleanProperty(config, "persistTranscript");
|
|
8156
|
+
const onToolFailureSay = extractStringProperty(config, "onToolFailureSay");
|
|
8103
8157
|
const volume = extractNumberProperty(config, "volume");
|
|
8104
8158
|
const interruption = extractObjectProperty(config, "interruption");
|
|
8105
8159
|
const pronunciationsRaw = extractObjectProperty(config, "pronunciations");
|
|
@@ -8136,6 +8190,7 @@ var init_voice_plugin = __esm({
|
|
|
8136
8190
|
hasTools: hasArrayProperty(config, "tools"),
|
|
8137
8191
|
krispEnabled,
|
|
8138
8192
|
persistTranscript,
|
|
8193
|
+
onToolFailureSay,
|
|
8139
8194
|
volume,
|
|
8140
8195
|
pronunciations,
|
|
8141
8196
|
backgroundAudio,
|
|
@@ -8195,6 +8250,7 @@ var init_voice_plugin = __esm({
|
|
|
8195
8250
|
if (fields.sttLanguage !== void 0) candidate.sttLanguage = fields.sttLanguage;
|
|
8196
8251
|
if (fields.krispEnabled !== void 0) candidate.krispEnabled = fields.krispEnabled;
|
|
8197
8252
|
if (fields.persistTranscript !== void 0) candidate.persistTranscript = fields.persistTranscript;
|
|
8253
|
+
if (fields.onToolFailureSay !== void 0) candidate.onToolFailureSay = fields.onToolFailureSay;
|
|
8198
8254
|
if (fields.volume !== void 0) candidate.volume = fields.volume;
|
|
8199
8255
|
if (fields.pronunciations !== void 0) candidate.pronunciations = fields.pronunciations;
|
|
8200
8256
|
if (fields.backgroundAudio !== void 0) candidate.backgroundAudio = fields.backgroundAudio;
|
|
@@ -8349,6 +8405,7 @@ var init_voice_plugin = __esm({
|
|
|
8349
8405
|
volume: fields.volume,
|
|
8350
8406
|
pronunciations: fields.pronunciations,
|
|
8351
8407
|
persistTranscript: fields.persistTranscript,
|
|
8408
|
+
onToolFailureSay: fields.onToolFailureSay,
|
|
8352
8409
|
interruption: fields.interruption
|
|
8353
8410
|
};
|
|
8354
8411
|
return entry;
|
|
@@ -15766,6 +15823,33 @@ var AgentHandler = class {
|
|
|
15766
15823
|
success: false
|
|
15767
15824
|
};
|
|
15768
15825
|
}
|
|
15826
|
+
const modelSettings = agent?.modelSettings ?? null;
|
|
15827
|
+
writeProgress("\n\u{1F321}\uFE0F Pushing model settings...");
|
|
15828
|
+
try {
|
|
15829
|
+
const success2 = await this.pushModelSettings({
|
|
15830
|
+
apiKey,
|
|
15831
|
+
agentId
|
|
15832
|
+
}, modelSettings);
|
|
15833
|
+
result.modelSettings = {
|
|
15834
|
+
success: success2
|
|
15835
|
+
};
|
|
15836
|
+
if (success2) {
|
|
15837
|
+
if (modelSettings !== null) {
|
|
15838
|
+
const keys = Object.keys(modelSettings).join(", ");
|
|
15839
|
+
writeSuccess(` \u2705 Model settings pushed (${keys})`);
|
|
15840
|
+
} else {
|
|
15841
|
+
writeSuccess(" \u2705 Model settings cleared (using provider defaults)");
|
|
15842
|
+
}
|
|
15843
|
+
} else {
|
|
15844
|
+
console.error(" \u274C Failed to push model settings");
|
|
15845
|
+
}
|
|
15846
|
+
} catch (error) {
|
|
15847
|
+
if (AuthenticationError.isAuthenticationError(error)) throw error;
|
|
15848
|
+
console.error(` \u274C Failed to push model settings: ${error.message}`);
|
|
15849
|
+
result.modelSettings = {
|
|
15850
|
+
success: false
|
|
15851
|
+
};
|
|
15852
|
+
}
|
|
15769
15853
|
const batching = agent?.batching ?? null;
|
|
15770
15854
|
writeProgress("\n\u23F1 Pushing batching configuration...");
|
|
15771
15855
|
try {
|
|
@@ -15899,6 +15983,13 @@ var AgentHandler = class {
|
|
|
15899
15983
|
});
|
|
15900
15984
|
return result.success;
|
|
15901
15985
|
}
|
|
15986
|
+
async pushModelSettings(ctx, modelSettings) {
|
|
15987
|
+
const agentApi = new AgentApi(BASE_URLS.API, ctx.apiKey);
|
|
15988
|
+
const result = await agentApi.updateAgent(ctx.agentId, {
|
|
15989
|
+
modelSettings
|
|
15990
|
+
});
|
|
15991
|
+
return result.success;
|
|
15992
|
+
}
|
|
15902
15993
|
async pushBatching(ctx, batchingConfig) {
|
|
15903
15994
|
const agentApi = new AgentApi(BASE_URLS.API, ctx.apiKey);
|
|
15904
15995
|
const result = await agentApi.updateAgent(ctx.agentId, {
|
|
@@ -16932,6 +17023,18 @@ async function safePrompt(questions) {
|
|
|
16932
17023
|
}
|
|
16933
17024
|
}
|
|
16934
17025
|
__name(safePrompt, "safePrompt");
|
|
17026
|
+
async function confirmAction(message) {
|
|
17027
|
+
const answer = await safePrompt([
|
|
17028
|
+
{
|
|
17029
|
+
type: "confirm",
|
|
17030
|
+
name: "confirmed",
|
|
17031
|
+
message,
|
|
17032
|
+
default: false
|
|
17033
|
+
}
|
|
17034
|
+
]);
|
|
17035
|
+
return answer?.confirmed ?? false;
|
|
17036
|
+
}
|
|
17037
|
+
__name(confirmAction, "confirmAction");
|
|
16935
17038
|
|
|
16936
17039
|
// src/commands/sync.ts
|
|
16937
17040
|
init_command_utils();
|
|
@@ -18666,6 +18769,7 @@ var VoiceHandler = class extends BaseVersionedHandler {
|
|
|
18666
18769
|
if (voice.hasTools !== void 0) body.hasTools = voice.hasTools;
|
|
18667
18770
|
if (voice.krispEnabled !== void 0) body.krispEnabled = voice.krispEnabled;
|
|
18668
18771
|
if (voice.persistTranscript !== void 0) body.persistTranscript = voice.persistTranscript;
|
|
18772
|
+
if (voice.onToolFailureSay !== void 0) body.onToolFailureSay = voice.onToolFailureSay;
|
|
18669
18773
|
if (voice.volume !== void 0) body.volume = voice.volume;
|
|
18670
18774
|
if (voice.pronunciations !== void 0) body.pronunciations = voice.pronunciations;
|
|
18671
18775
|
if (voice.backgroundAudio !== void 0) body.backgroundAudio = voice.backgroundAudio;
|
|
@@ -22139,6 +22243,507 @@ __name(getCommitSha, "getCommitSha");
|
|
|
22139
22243
|
|
|
22140
22244
|
// src/utils/try-git-commit.ts
|
|
22141
22245
|
init_analytics();
|
|
22246
|
+
|
|
22247
|
+
// src/utils/auto-push-hook.ts
|
|
22248
|
+
init_cli();
|
|
22249
|
+
|
|
22250
|
+
// src/utils/git-auth-store.ts
|
|
22251
|
+
init_constants();
|
|
22252
|
+
import { mkdirSync as mkdirSync7, readFileSync as readFileSync10, writeFileSync as writeFileSync7 } from "fs";
|
|
22253
|
+
import { dirname as dirname6 } from "path";
|
|
22254
|
+
function readStore() {
|
|
22255
|
+
try {
|
|
22256
|
+
const raw = readFileSync10(AUTH_STORAGE_FILE, "utf8");
|
|
22257
|
+
const parsed = JSON.parse(raw);
|
|
22258
|
+
return {
|
|
22259
|
+
providers: parsed.providers ?? {}
|
|
22260
|
+
};
|
|
22261
|
+
} catch {
|
|
22262
|
+
return {
|
|
22263
|
+
providers: {}
|
|
22264
|
+
};
|
|
22265
|
+
}
|
|
22266
|
+
}
|
|
22267
|
+
__name(readStore, "readStore");
|
|
22268
|
+
function writeStore(store) {
|
|
22269
|
+
mkdirSync7(dirname6(AUTH_STORAGE_FILE), {
|
|
22270
|
+
recursive: true
|
|
22271
|
+
});
|
|
22272
|
+
writeFileSync7(AUTH_STORAGE_FILE, JSON.stringify(store, null, 2), {
|
|
22273
|
+
mode: 384
|
|
22274
|
+
});
|
|
22275
|
+
}
|
|
22276
|
+
__name(writeStore, "writeStore");
|
|
22277
|
+
async function saveAuth(provider, record) {
|
|
22278
|
+
const store = readStore();
|
|
22279
|
+
store.providers[provider] = record;
|
|
22280
|
+
writeStore(store);
|
|
22281
|
+
}
|
|
22282
|
+
__name(saveAuth, "saveAuth");
|
|
22283
|
+
async function getToken2(provider) {
|
|
22284
|
+
return readStore().providers[provider]?.token ?? null;
|
|
22285
|
+
}
|
|
22286
|
+
__name(getToken2, "getToken");
|
|
22287
|
+
async function getStatus(provider) {
|
|
22288
|
+
const record = readStore().providers[provider];
|
|
22289
|
+
if (!record) return {
|
|
22290
|
+
linked: false
|
|
22291
|
+
};
|
|
22292
|
+
return {
|
|
22293
|
+
linked: true,
|
|
22294
|
+
username: record.username,
|
|
22295
|
+
scopes: record.scopes,
|
|
22296
|
+
linkedAt: record.linkedAt
|
|
22297
|
+
};
|
|
22298
|
+
}
|
|
22299
|
+
__name(getStatus, "getStatus");
|
|
22300
|
+
async function clearAuth(provider) {
|
|
22301
|
+
const store = readStore();
|
|
22302
|
+
delete store.providers[provider];
|
|
22303
|
+
writeStore(store);
|
|
22304
|
+
}
|
|
22305
|
+
__name(clearAuth, "clearAuth");
|
|
22306
|
+
|
|
22307
|
+
// src/utils/git-providers/github-provider.ts
|
|
22308
|
+
import { createServer } from "http";
|
|
22309
|
+
import { randomBytes as randomBytes2 } from "crypto";
|
|
22310
|
+
import { request } from "undici";
|
|
22311
|
+
import open from "open";
|
|
22312
|
+
|
|
22313
|
+
// src/config/git-providers.constants.ts
|
|
22314
|
+
var GITHUB_CLIENT_ID = "Ov23lipe1jgBlCsoi9OO";
|
|
22315
|
+
var GITHUB_OAUTH_BASE_URL = "https://github.com";
|
|
22316
|
+
var GITHUB_API_BASE_URL = "https://api.github.com";
|
|
22317
|
+
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
|
+
var DEVICE_FLOW_DEFAULT_INTERVAL_MS = 5e3;
|
|
22323
|
+
var DEVICE_FLOW_SLOW_DOWN_INCREMENT_MS = 5e3;
|
|
22324
|
+
var PUSH_TIMEOUT_MS = 2 * 60 * 1e3;
|
|
22325
|
+
|
|
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
|
+
// src/interfaces/git-providers.ts
|
|
22342
|
+
var GitPushError = class extends Error {
|
|
22343
|
+
static {
|
|
22344
|
+
__name(this, "GitPushError");
|
|
22345
|
+
}
|
|
22346
|
+
status;
|
|
22347
|
+
scrubbedStderr;
|
|
22348
|
+
constructor(message, status, scrubbedStderr) {
|
|
22349
|
+
super(message), this.status = status, this.scrubbedStderr = scrubbedStderr;
|
|
22350
|
+
this.name = "GitPushError";
|
|
22351
|
+
}
|
|
22352
|
+
};
|
|
22353
|
+
|
|
22354
|
+
// src/utils/git-providers/github-provider.ts
|
|
22355
|
+
init_cli();
|
|
22356
|
+
|
|
22357
|
+
// src/utils/scrub-token.ts
|
|
22358
|
+
function scrubToken(s, token) {
|
|
22359
|
+
if (!token) return s;
|
|
22360
|
+
return s.split(token).join("<redacted>");
|
|
22361
|
+
}
|
|
22362
|
+
__name(scrubToken, "scrubToken");
|
|
22363
|
+
|
|
22364
|
+
// 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
|
+
var GitHubProvider = class {
|
|
22371
|
+
static {
|
|
22372
|
+
__name(this, "GitHubProvider");
|
|
22373
|
+
}
|
|
22374
|
+
name = "github";
|
|
22375
|
+
async login(opts) {
|
|
22376
|
+
const token = opts.device ? await this.deviceFlow() : await this.loopbackFlow();
|
|
22377
|
+
const username = await this.fetchUsername(token);
|
|
22378
|
+
await saveAuth(this.name, {
|
|
22379
|
+
token,
|
|
22380
|
+
username,
|
|
22381
|
+
scopes: [
|
|
22382
|
+
GITHUB_OAUTH_SCOPE
|
|
22383
|
+
],
|
|
22384
|
+
linkedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
22385
|
+
});
|
|
22386
|
+
return {
|
|
22387
|
+
username
|
|
22388
|
+
};
|
|
22389
|
+
}
|
|
22390
|
+
async logout() {
|
|
22391
|
+
await clearAuth(this.name);
|
|
22392
|
+
}
|
|
22393
|
+
async status() {
|
|
22394
|
+
return getStatus(this.name);
|
|
22395
|
+
}
|
|
22396
|
+
async push(opts) {
|
|
22397
|
+
const parsed = parseGitHubHttpsUrl(opts.remoteUrl);
|
|
22398
|
+
const authedUrl = `https://x-access-token:${opts.token}@github.com/${parsed.owner}/${parsed.repo}`;
|
|
22399
|
+
let result;
|
|
22400
|
+
try {
|
|
22401
|
+
result = await runGit([
|
|
22402
|
+
"push",
|
|
22403
|
+
authedUrl,
|
|
22404
|
+
opts.branch
|
|
22405
|
+
], {
|
|
22406
|
+
cwd: opts.cwd,
|
|
22407
|
+
timeout: PUSH_TIMEOUT_MS
|
|
22408
|
+
});
|
|
22409
|
+
} catch (err) {
|
|
22410
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
22411
|
+
const scrubbed2 = scrubToken(raw, opts.token);
|
|
22412
|
+
throw new GitPushError(`git push failed: ${scrubbed2}`, 0, scrubbed2);
|
|
22413
|
+
}
|
|
22414
|
+
if (result.code === 0) return;
|
|
22415
|
+
const scrubbed = scrubToken(result.stderr, opts.token);
|
|
22416
|
+
const status = matchPushStatus(scrubbed);
|
|
22417
|
+
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
|
+
}
|
|
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
|
+
async fetchUsername(token) {
|
|
22540
|
+
const res = await request(`${GITHUB_API_BASE_URL}/user`, {
|
|
22541
|
+
method: "GET",
|
|
22542
|
+
headers: {
|
|
22543
|
+
accept: "application/vnd.github+json",
|
|
22544
|
+
authorization: `Bearer ${token}`,
|
|
22545
|
+
"user-agent": "lua-cli"
|
|
22546
|
+
}
|
|
22547
|
+
});
|
|
22548
|
+
const body = await res.body.json();
|
|
22549
|
+
if (!body.login) throw new Error("Could not read GitHub username after auth.");
|
|
22550
|
+
return body.login;
|
|
22551
|
+
}
|
|
22552
|
+
async deviceFlow() {
|
|
22553
|
+
const codeRes = await request(`${GITHUB_OAUTH_BASE_URL}/login/device/code`, {
|
|
22554
|
+
method: "POST",
|
|
22555
|
+
headers: {
|
|
22556
|
+
accept: "application/json",
|
|
22557
|
+
"content-type": "application/json"
|
|
22558
|
+
},
|
|
22559
|
+
body: JSON.stringify({
|
|
22560
|
+
client_id: GITHUB_CLIENT_ID,
|
|
22561
|
+
scope: GITHUB_OAUTH_SCOPE
|
|
22562
|
+
})
|
|
22563
|
+
});
|
|
22564
|
+
const codeBody = await codeRes.body.json();
|
|
22565
|
+
if (!codeBody.device_code || !codeBody.user_code || !codeBody.verification_uri) {
|
|
22566
|
+
throw new Error(`GitHub rejected device-code request: ${codeBody.error ?? "unknown error"}`);
|
|
22567
|
+
}
|
|
22568
|
+
writeInfo(`Open ${codeBody.verification_uri} and enter the code: ${codeBody.user_code}`);
|
|
22569
|
+
let intervalMs = codeBody.interval != null ? codeBody.interval * 1e3 : DEVICE_FLOW_DEFAULT_INTERVAL_MS;
|
|
22570
|
+
const deadline = Date.now() + (codeBody.expires_in ?? 900) * 1e3;
|
|
22571
|
+
while (Date.now() < deadline) {
|
|
22572
|
+
await sleep(intervalMs);
|
|
22573
|
+
if (Date.now() >= deadline) break;
|
|
22574
|
+
const pollRes = await request(`${GITHUB_OAUTH_BASE_URL}/login/oauth/access_token`, {
|
|
22575
|
+
method: "POST",
|
|
22576
|
+
headers: {
|
|
22577
|
+
accept: "application/json",
|
|
22578
|
+
"content-type": "application/json"
|
|
22579
|
+
},
|
|
22580
|
+
body: JSON.stringify({
|
|
22581
|
+
client_id: GITHUB_CLIENT_ID,
|
|
22582
|
+
device_code: codeBody.device_code,
|
|
22583
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code"
|
|
22584
|
+
})
|
|
22585
|
+
});
|
|
22586
|
+
const body = await pollRes.body.json();
|
|
22587
|
+
if (body.access_token) return body.access_token;
|
|
22588
|
+
if (body.error === "authorization_pending") continue;
|
|
22589
|
+
if (body.error === "slow_down") {
|
|
22590
|
+
intervalMs += DEVICE_FLOW_SLOW_DOWN_INCREMENT_MS;
|
|
22591
|
+
continue;
|
|
22592
|
+
}
|
|
22593
|
+
if (body.error === "expired_token") {
|
|
22594
|
+
throw new Error("Device code expired. Re-run `lua git auth github --device`.");
|
|
22595
|
+
}
|
|
22596
|
+
throw new Error(`GitHub device-flow error: ${body.error ?? "unknown"}`);
|
|
22597
|
+
}
|
|
22598
|
+
throw new Error("Device flow timed out. Re-run `lua git auth github --device`.");
|
|
22599
|
+
}
|
|
22600
|
+
};
|
|
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
|
+
function sleep(ms) {
|
|
22611
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
22612
|
+
}
|
|
22613
|
+
__name(sleep, "sleep");
|
|
22614
|
+
function isGitHubUrl(url) {
|
|
22615
|
+
try {
|
|
22616
|
+
const u = new URL(url);
|
|
22617
|
+
return u.protocol === "https:" && u.hostname === "github.com";
|
|
22618
|
+
} catch {
|
|
22619
|
+
return false;
|
|
22620
|
+
}
|
|
22621
|
+
}
|
|
22622
|
+
__name(isGitHubUrl, "isGitHubUrl");
|
|
22623
|
+
function parseGitHubHttpsUrl(url) {
|
|
22624
|
+
let u;
|
|
22625
|
+
try {
|
|
22626
|
+
u = new URL(url);
|
|
22627
|
+
} catch {
|
|
22628
|
+
throw new Error(`Not a parseable URL: ${url}. v1 only supports https GitHub remotes.`);
|
|
22629
|
+
}
|
|
22630
|
+
if (u.protocol !== "https:" || u.hostname !== "github.com") {
|
|
22631
|
+
throw new Error(`Not a GitHub HTTPS remote: ${url}. v1 only supports https://github.com/...`);
|
|
22632
|
+
}
|
|
22633
|
+
const parts = u.pathname.replace(/^\/+/, "").replace(/\.git$/, "").split("/");
|
|
22634
|
+
if (parts.length < 2 || !parts[0] || !parts[1]) {
|
|
22635
|
+
throw new Error(`Unexpected GitHub URL shape: ${url}`);
|
|
22636
|
+
}
|
|
22637
|
+
return {
|
|
22638
|
+
owner: parts[0],
|
|
22639
|
+
repo: parts[1]
|
|
22640
|
+
};
|
|
22641
|
+
}
|
|
22642
|
+
__name(parseGitHubHttpsUrl, "parseGitHubHttpsUrl");
|
|
22643
|
+
function matchPushStatus(stderr) {
|
|
22644
|
+
const s = stderr.toLowerCase();
|
|
22645
|
+
if (s.includes("401") || s.includes("authentication failed")) return 401;
|
|
22646
|
+
if (s.includes("403") || s.includes("permission to") || s.includes("forbidden")) return 403;
|
|
22647
|
+
return 0;
|
|
22648
|
+
}
|
|
22649
|
+
__name(matchPushStatus, "matchPushStatus");
|
|
22650
|
+
|
|
22651
|
+
// src/utils/auto-push-hook.ts
|
|
22652
|
+
init_analytics();
|
|
22653
|
+
var warned = /* @__PURE__ */ new Set();
|
|
22654
|
+
function warnOnce(key, message) {
|
|
22655
|
+
if (warned.has(key)) return;
|
|
22656
|
+
warned.add(key);
|
|
22657
|
+
writeInfo(`\u26A0\uFE0F ${message}`);
|
|
22658
|
+
}
|
|
22659
|
+
__name(warnOnce, "warnOnce");
|
|
22660
|
+
async function tryGitAutoPush(ctx) {
|
|
22661
|
+
try {
|
|
22662
|
+
if (ctx.config?.git?.autoPush !== true) return;
|
|
22663
|
+
const token = await getToken2("github");
|
|
22664
|
+
if (!token) {
|
|
22665
|
+
warnOnce("missing-github-token", "git.autoPush is enabled but no GitHub auth \u2014 run `lua git auth github`.");
|
|
22666
|
+
return;
|
|
22667
|
+
}
|
|
22668
|
+
const remote = await readRemoteOriginUrl(ctx.cwd);
|
|
22669
|
+
if (!remote) {
|
|
22670
|
+
warnOnce("missing-github-remote", "git.autoPush is enabled but no `remote.origin.url` is set. Skipping push.");
|
|
22671
|
+
return;
|
|
22672
|
+
}
|
|
22673
|
+
if (!isGitHubUrl(remote)) {
|
|
22674
|
+
warnOnce("non-github-remote", `git.autoPush is enabled but origin (${remote}) is not a supported GitHub HTTPS URL. v1 only supports https://github.com/<owner>/<repo> \u2014 skipping push.`);
|
|
22675
|
+
return;
|
|
22676
|
+
}
|
|
22677
|
+
const branch = await readCurrentBranch(ctx.cwd);
|
|
22678
|
+
if (!branch) {
|
|
22679
|
+
warnOnce("detached-head", "Cannot auto-push from a detached HEAD. Skipping push.");
|
|
22680
|
+
return;
|
|
22681
|
+
}
|
|
22682
|
+
const provider = new GitHubProvider();
|
|
22683
|
+
try {
|
|
22684
|
+
await provider.push({
|
|
22685
|
+
token,
|
|
22686
|
+
remoteUrl: remote,
|
|
22687
|
+
branch,
|
|
22688
|
+
cwd: ctx.cwd ?? process.cwd()
|
|
22689
|
+
});
|
|
22690
|
+
writeInfo(`\u2713 Pushed ${ctx.commitSha?.slice(0, 7) ?? ""} to ${remote} (${branch})`);
|
|
22691
|
+
trackEvent("cli_auto_push_succeeded", {
|
|
22692
|
+
action: ctx.action
|
|
22693
|
+
});
|
|
22694
|
+
} catch (err) {
|
|
22695
|
+
const status = err instanceof GitPushError ? err.status : 0;
|
|
22696
|
+
const message = err instanceof GitPushError ? err.scrubbedStderr || err.message : err instanceof Error ? err.message : String(err);
|
|
22697
|
+
if (status === 401) {
|
|
22698
|
+
warnOnce("push-revoked", "GitHub auth was revoked \u2014 run `lua git auth github` to re-link. Commit kept locally.");
|
|
22699
|
+
} else if (status === 403) {
|
|
22700
|
+
warnOnce("push-rejected-403", `GitHub rejected the push: ${message}. Commit kept locally.`);
|
|
22701
|
+
} else {
|
|
22702
|
+
warnOnce("push-failed-other", `Auto-push failed: ${message}. Commit kept locally; run \`git push\` to retry.`);
|
|
22703
|
+
}
|
|
22704
|
+
trackEvent("cli_auto_push_failed", {
|
|
22705
|
+
action: ctx.action,
|
|
22706
|
+
status
|
|
22707
|
+
});
|
|
22708
|
+
}
|
|
22709
|
+
} catch {
|
|
22710
|
+
warnOnce("hook-errored", "Auto-push hook errored unexpectedly. Commit kept locally; run `git push` to retry.");
|
|
22711
|
+
trackEvent("cli_auto_push_failed", {
|
|
22712
|
+
action: ctx.action,
|
|
22713
|
+
status: 0
|
|
22714
|
+
});
|
|
22715
|
+
}
|
|
22716
|
+
}
|
|
22717
|
+
__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
|
+
async function readCurrentBranch(cwd) {
|
|
22732
|
+
const res = await runGit([
|
|
22733
|
+
"rev-parse",
|
|
22734
|
+
"--abbrev-ref",
|
|
22735
|
+
"HEAD"
|
|
22736
|
+
], {
|
|
22737
|
+
cwd
|
|
22738
|
+
});
|
|
22739
|
+
if (res.code !== 0) return null;
|
|
22740
|
+
const trimmed = res.stdout.trim();
|
|
22741
|
+
if (!trimmed || trimmed === "HEAD") return null;
|
|
22742
|
+
return trimmed;
|
|
22743
|
+
}
|
|
22744
|
+
__name(readCurrentBranch, "readCurrentBranch");
|
|
22745
|
+
|
|
22746
|
+
// src/utils/try-git-commit.ts
|
|
22142
22747
|
async function tryGitCommit(opts) {
|
|
22143
22748
|
const config = readYamlConfig();
|
|
22144
22749
|
if (!config?.git?.enabled) {
|
|
@@ -22221,6 +22826,12 @@ async function tryGitCommit(opts) {
|
|
|
22221
22826
|
has_sha: Boolean(sha),
|
|
22222
22827
|
has_tag: tagged === true
|
|
22223
22828
|
});
|
|
22829
|
+
await tryGitAutoPush({
|
|
22830
|
+
config,
|
|
22831
|
+
cwd: opts.cwd,
|
|
22832
|
+
commitSha: sha,
|
|
22833
|
+
action: opts.action
|
|
22834
|
+
});
|
|
22224
22835
|
return {
|
|
22225
22836
|
committed: true,
|
|
22226
22837
|
sha,
|
|
@@ -24154,11 +24765,11 @@ init_cli();
|
|
|
24154
24765
|
|
|
24155
24766
|
// src/utils/sandbox-storage.ts
|
|
24156
24767
|
init_constants();
|
|
24157
|
-
import { readFileSync as
|
|
24158
|
-
import { dirname as
|
|
24159
|
-
function
|
|
24768
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8 } from "fs";
|
|
24769
|
+
import { dirname as dirname7 } from "path";
|
|
24770
|
+
function readStore2() {
|
|
24160
24771
|
try {
|
|
24161
|
-
const raw =
|
|
24772
|
+
const raw = readFileSync11(SANDBOX_STORAGE_FILE, "utf8");
|
|
24162
24773
|
const parsed = JSON.parse(raw);
|
|
24163
24774
|
return {
|
|
24164
24775
|
skills: parsed.skills ?? {},
|
|
@@ -24175,28 +24786,28 @@ function readStore() {
|
|
|
24175
24786
|
};
|
|
24176
24787
|
}
|
|
24177
24788
|
}
|
|
24178
|
-
__name(
|
|
24179
|
-
function
|
|
24789
|
+
__name(readStore2, "readStore");
|
|
24790
|
+
function writeStore2(store) {
|
|
24180
24791
|
try {
|
|
24181
|
-
|
|
24792
|
+
mkdirSync8(dirname7(SANDBOX_STORAGE_FILE), {
|
|
24182
24793
|
recursive: true
|
|
24183
24794
|
});
|
|
24184
|
-
|
|
24795
|
+
writeFileSync8(SANDBOX_STORAGE_FILE, JSON.stringify(store, null, 2), "utf8");
|
|
24185
24796
|
} catch {
|
|
24186
24797
|
}
|
|
24187
24798
|
}
|
|
24188
|
-
__name(
|
|
24799
|
+
__name(writeStore2, "writeStore");
|
|
24189
24800
|
async function getSandboxSkillId(skillName) {
|
|
24190
|
-
const store =
|
|
24801
|
+
const store = readStore2();
|
|
24191
24802
|
const key = skillName ?? "__default__";
|
|
24192
24803
|
return store.skills[key] ?? null;
|
|
24193
24804
|
}
|
|
24194
24805
|
__name(getSandboxSkillId, "getSandboxSkillId");
|
|
24195
24806
|
async function setSandboxSkillId(sandboxId, skillName) {
|
|
24196
|
-
const store =
|
|
24807
|
+
const store = readStore2();
|
|
24197
24808
|
const key = skillName ?? "__default__";
|
|
24198
24809
|
store.skills[key] = sandboxId;
|
|
24199
|
-
|
|
24810
|
+
writeStore2(store);
|
|
24200
24811
|
}
|
|
24201
24812
|
__name(setSandboxSkillId, "setSandboxSkillId");
|
|
24202
24813
|
async function getAllSandboxSkillIds(yamlConfig) {
|
|
@@ -24222,14 +24833,14 @@ async function getAllSandboxSkillIds(yamlConfig) {
|
|
|
24222
24833
|
}
|
|
24223
24834
|
__name(getAllSandboxSkillIds, "getAllSandboxSkillIds");
|
|
24224
24835
|
async function getSandboxPreProcessorId(preprocessorName) {
|
|
24225
|
-
const store =
|
|
24836
|
+
const store = readStore2();
|
|
24226
24837
|
return store.preprocessors[preprocessorName] ?? null;
|
|
24227
24838
|
}
|
|
24228
24839
|
__name(getSandboxPreProcessorId, "getSandboxPreProcessorId");
|
|
24229
24840
|
async function setSandboxPreProcessorId(sandboxId, preprocessorName) {
|
|
24230
|
-
const store =
|
|
24841
|
+
const store = readStore2();
|
|
24231
24842
|
store.preprocessors[preprocessorName] = sandboxId;
|
|
24232
|
-
|
|
24843
|
+
writeStore2(store);
|
|
24233
24844
|
}
|
|
24234
24845
|
__name(setSandboxPreProcessorId, "setSandboxPreProcessorId");
|
|
24235
24846
|
async function getAllSandboxPreProcessorIds(config) {
|
|
@@ -24254,14 +24865,14 @@ async function getAllSandboxPreProcessorIds(config) {
|
|
|
24254
24865
|
}
|
|
24255
24866
|
__name(getAllSandboxPreProcessorIds, "getAllSandboxPreProcessorIds");
|
|
24256
24867
|
async function getSandboxPostProcessorId(postprocessorName) {
|
|
24257
|
-
const store =
|
|
24868
|
+
const store = readStore2();
|
|
24258
24869
|
return store.postprocessors[postprocessorName] ?? null;
|
|
24259
24870
|
}
|
|
24260
24871
|
__name(getSandboxPostProcessorId, "getSandboxPostProcessorId");
|
|
24261
24872
|
async function setSandboxPostProcessorId(sandboxId, postprocessorName) {
|
|
24262
|
-
const store =
|
|
24873
|
+
const store = readStore2();
|
|
24263
24874
|
store.postprocessors[postprocessorName] = sandboxId;
|
|
24264
|
-
|
|
24875
|
+
writeStore2(store);
|
|
24265
24876
|
}
|
|
24266
24877
|
__name(setSandboxPostProcessorId, "setSandboxPostProcessorId");
|
|
24267
24878
|
async function getAllSandboxPostProcessorIds(config) {
|
|
@@ -27593,7 +28204,7 @@ __name(viewResourceInteractive, "viewResourceInteractive");
|
|
|
27593
28204
|
init_cli();
|
|
27594
28205
|
init_command_utils();
|
|
27595
28206
|
init_analytics();
|
|
27596
|
-
import
|
|
28207
|
+
import open2 from "open";
|
|
27597
28208
|
async function adminCommand() {
|
|
27598
28209
|
return withErrorHandling(async () => {
|
|
27599
28210
|
writeProgress("Opening Lua Admin Dashboard...");
|
|
@@ -27601,7 +28212,7 @@ async function adminCommand() {
|
|
|
27601
28212
|
showProgress: false
|
|
27602
28213
|
});
|
|
27603
28214
|
const adminUrl = `https://admin.heylua.ai/validate-token/${apiKey}?redirect=/admin/usage?&agentId=${agentId}&orgId=${orgId}`;
|
|
27604
|
-
await
|
|
28215
|
+
await open2(adminUrl);
|
|
27605
28216
|
writeSuccess("Lua Admin Dashboard opened in your browser");
|
|
27606
28217
|
console.log(`
|
|
27607
28218
|
Dashboard URL: https://admin.heylua.ai`);
|
|
@@ -27617,7 +28228,7 @@ __name(adminCommand, "adminCommand");
|
|
|
27617
28228
|
init_cli();
|
|
27618
28229
|
init_command_utils();
|
|
27619
28230
|
init_analytics();
|
|
27620
|
-
import
|
|
28231
|
+
import open3 from "open";
|
|
27621
28232
|
async function evalsCommand() {
|
|
27622
28233
|
return withErrorHandling(async () => {
|
|
27623
28234
|
writeProgress("Opening Lua Evaluations Dashboard...");
|
|
@@ -27625,7 +28236,7 @@ async function evalsCommand() {
|
|
|
27625
28236
|
showProgress: false
|
|
27626
28237
|
});
|
|
27627
28238
|
const evalsUrl = `https://evals.heylua.ai?apiKey=${apiKey}&agentID=${agentId}`;
|
|
27628
|
-
await
|
|
28239
|
+
await open3(evalsUrl);
|
|
27629
28240
|
writeSuccess("Lua Evaluations Dashboard opened in your browser");
|
|
27630
28241
|
console.log(`
|
|
27631
28242
|
Dashboard URL: https://evals.heylua.ai`);
|
|
@@ -27639,12 +28250,12 @@ __name(evalsCommand, "evalsCommand");
|
|
|
27639
28250
|
// src/commands/docs.ts
|
|
27640
28251
|
init_cli();
|
|
27641
28252
|
init_analytics();
|
|
27642
|
-
import
|
|
28253
|
+
import open4 from "open";
|
|
27643
28254
|
async function docsCommand() {
|
|
27644
28255
|
return withErrorHandling(async () => {
|
|
27645
28256
|
writeProgress("Opening Lua Documentation...");
|
|
27646
28257
|
const docsUrl = "https://docs.heylua.ai";
|
|
27647
|
-
await
|
|
28258
|
+
await open4(docsUrl);
|
|
27648
28259
|
writeSuccess("Lua Documentation opened in your browser");
|
|
27649
28260
|
console.log(`
|
|
27650
28261
|
Documentation: ${docsUrl}
|
|
@@ -27658,7 +28269,7 @@ __name(docsCommand, "docsCommand");
|
|
|
27658
28269
|
init_cli();
|
|
27659
28270
|
init_command_utils();
|
|
27660
28271
|
import inquirer12 from "inquirer";
|
|
27661
|
-
import
|
|
28272
|
+
import open5 from "open";
|
|
27662
28273
|
|
|
27663
28274
|
// src/api/channels.api.service.ts
|
|
27664
28275
|
init_http_client();
|
|
@@ -28227,7 +28838,7 @@ async function openAdminDashboard(apiKey, config) {
|
|
|
28227
28838
|
throw new Error("No orgId found in lua.skill.yaml. Please ensure your configuration is valid.");
|
|
28228
28839
|
}
|
|
28229
28840
|
const adminUrl = `https://admin.heylua.ai/validate-token/${apiKey}?redirect=/admin/usage?&agentId=${agentId}&orgId=${orgId}`;
|
|
28230
|
-
await
|
|
28841
|
+
await open5(adminUrl);
|
|
28231
28842
|
writeSuccess("\u2705 Lua Admin Dashboard opened in your browser");
|
|
28232
28843
|
console.log(`
|
|
28233
28844
|
Dashboard URL: https://admin.heylua.ai`);
|
|
@@ -30358,7 +30969,7 @@ init_auth();
|
|
|
30358
30969
|
init_auth_api_service();
|
|
30359
30970
|
init_files();
|
|
30360
30971
|
init_artifact_loader();
|
|
30361
|
-
import { existsSync as existsSync7, readFileSync as
|
|
30972
|
+
import { existsSync as existsSync7, readFileSync as readFileSync12 } from "fs";
|
|
30362
30973
|
import { join as join6 } from "path";
|
|
30363
30974
|
import { performance } from "perf_hooks";
|
|
30364
30975
|
import * as os from "os";
|
|
@@ -30709,7 +31320,7 @@ function gatherTelemetry() {
|
|
|
30709
31320
|
} else {
|
|
30710
31321
|
try {
|
|
30711
31322
|
if (existsSync7(TELEMETRY_FILE)) {
|
|
30712
|
-
const raw =
|
|
31323
|
+
const raw = readFileSync12(TELEMETRY_FILE, "utf8");
|
|
30713
31324
|
const cfg = JSON.parse(raw);
|
|
30714
31325
|
if (typeof cfg.enabled === "boolean") enabled = cfg.enabled;
|
|
30715
31326
|
}
|
|
@@ -37011,7 +37622,7 @@ init_cli();
|
|
|
37011
37622
|
init_constants();
|
|
37012
37623
|
import http from "http";
|
|
37013
37624
|
import { URL as URL2 } from "url";
|
|
37014
|
-
import
|
|
37625
|
+
import open6 from "open";
|
|
37015
37626
|
init_command_utils();
|
|
37016
37627
|
init_developer_api_service();
|
|
37017
37628
|
|
|
@@ -38034,7 +38645,7 @@ Integration: ${selectedIntegration.name}`);
|
|
|
38034
38645
|
`);
|
|
38035
38646
|
const callbackPromise = startCallbackServer(3e5);
|
|
38036
38647
|
try {
|
|
38037
|
-
await
|
|
38648
|
+
await open6(authUrl);
|
|
38038
38649
|
writeInfo("\u{1F310} Browser opened - please complete the authorization");
|
|
38039
38650
|
} catch (error) {
|
|
38040
38651
|
writeInfo("\u{1F4A1} Could not open browser automatically. Please open the URL above manually.");
|
|
@@ -38465,7 +39076,7 @@ Available scopes for ${selectedIntegration.name}:`);
|
|
|
38465
39076
|
`);
|
|
38466
39077
|
const callbackPromise = startCallbackServer(3e5);
|
|
38467
39078
|
try {
|
|
38468
|
-
await
|
|
39079
|
+
await open6(authUrl);
|
|
38469
39080
|
writeInfo("\u{1F310} Browser opened - please complete the authorization");
|
|
38470
39081
|
} catch (error) {
|
|
38471
39082
|
writeInfo("\u{1F4A1} Could not open browser automatically. Please open the URL above manually.");
|
|
@@ -39890,7 +40501,7 @@ __name(telemetryCommand, "telemetryCommand");
|
|
|
39890
40501
|
init_cli();
|
|
39891
40502
|
init_command_utils();
|
|
39892
40503
|
init_analytics();
|
|
39893
|
-
import { writeFileSync as
|
|
40504
|
+
import { writeFileSync as writeFileSync9, existsSync as existsSync8, unlinkSync as unlinkSync2 } from "fs";
|
|
39894
40505
|
import { resolve as resolve4, join as join7 } from "path";
|
|
39895
40506
|
init_artifact_loader();
|
|
39896
40507
|
init_types();
|
|
@@ -40051,7 +40662,7 @@ async function governanceCommand(action) {
|
|
|
40051
40662
|
}
|
|
40052
40663
|
}
|
|
40053
40664
|
const content = generateFile(setup);
|
|
40054
|
-
|
|
40665
|
+
writeFileSync9(filePath, content, "utf-8");
|
|
40055
40666
|
const relativePath = filePath.replace(process.cwd() + "/", "");
|
|
40056
40667
|
writeSuccess(`Created ${relativePath}`);
|
|
40057
40668
|
console.log("");
|
|
@@ -40678,7 +41289,7 @@ __name(pumpRemoteAudioToSpeaker, "pumpRemoteAudioToSpeaker");
|
|
|
40678
41289
|
// src/commands/voice-browser.ts
|
|
40679
41290
|
init_cli();
|
|
40680
41291
|
import http2 from "http";
|
|
40681
|
-
import
|
|
41292
|
+
import open7 from "open";
|
|
40682
41293
|
var SAFETY_TIMEOUT_MS = 60 * 60 * 1e3;
|
|
40683
41294
|
async function runBrowserMode(joinUrl) {
|
|
40684
41295
|
const { wsUrl, token } = parseJoinUrl(joinUrl);
|
|
@@ -40710,7 +41321,7 @@ async function runBrowserMode(joinUrl) {
|
|
|
40710
41321
|
const localUrl = `http://localhost:${port}/`;
|
|
40711
41322
|
writeSuccess(`Voice room ready (opening browser)`);
|
|
40712
41323
|
console.log(` ${localUrl}`);
|
|
40713
|
-
await
|
|
41324
|
+
await open7(localUrl);
|
|
40714
41325
|
await new Promise((resolve6) => {
|
|
40715
41326
|
const safety = setTimeout(() => {
|
|
40716
41327
|
try {
|
|
@@ -41903,6 +42514,77 @@ async function gitStatusCommand() {
|
|
|
41903
42514
|
}
|
|
41904
42515
|
__name(gitStatusCommand, "gitStatusCommand");
|
|
41905
42516
|
|
|
42517
|
+
// src/commands/git-auth.ts
|
|
42518
|
+
init_cli();
|
|
42519
|
+
init_analytics();
|
|
42520
|
+
function gitAuthGithubCommand(opts) {
|
|
42521
|
+
return withErrorHandling(async () => {
|
|
42522
|
+
const provider = new GitHubProvider();
|
|
42523
|
+
const existing = await provider.status();
|
|
42524
|
+
if (existing.linked && !opts.force) {
|
|
42525
|
+
const ok = await confirmAction(`Already linked to GitHub as @${existing.username}. Re-link?`);
|
|
42526
|
+
if (!ok) {
|
|
42527
|
+
writeInfo("Aborted. Existing link preserved.");
|
|
42528
|
+
return;
|
|
42529
|
+
}
|
|
42530
|
+
}
|
|
42531
|
+
const result = await provider.login({
|
|
42532
|
+
device: opts.device,
|
|
42533
|
+
force: opts.force
|
|
42534
|
+
});
|
|
42535
|
+
writeSuccess(`Logged in to GitHub as @${result.username}.`);
|
|
42536
|
+
trackEvent("cli_git_auth_succeeded", {
|
|
42537
|
+
provider: "github",
|
|
42538
|
+
flow: opts.device ? "device" : "loopback"
|
|
42539
|
+
});
|
|
42540
|
+
}, "git-auth-github");
|
|
42541
|
+
}
|
|
42542
|
+
__name(gitAuthGithubCommand, "gitAuthGithubCommand");
|
|
42543
|
+
function gitAuthStatusCommand() {
|
|
42544
|
+
return withErrorHandling(async () => {
|
|
42545
|
+
const provider = new GitHubProvider();
|
|
42546
|
+
const s = await provider.status();
|
|
42547
|
+
if (!s.linked) {
|
|
42548
|
+
console.log("Not linked. Run `lua git auth github` to link.");
|
|
42549
|
+
} else {
|
|
42550
|
+
console.log(`Linked: github \u2014 @${s.username} (scopes: ${s.scopes.join(", ")}) \u2014 linked ${formatLinkedAt(s.linkedAt)}`);
|
|
42551
|
+
}
|
|
42552
|
+
trackEvent("cli_git_auth_status_completed", {
|
|
42553
|
+
linked: s.linked
|
|
42554
|
+
});
|
|
42555
|
+
}, "git-auth-status");
|
|
42556
|
+
}
|
|
42557
|
+
__name(gitAuthStatusCommand, "gitAuthStatusCommand");
|
|
42558
|
+
function gitAuthDisconnectCommand(provider) {
|
|
42559
|
+
return withErrorHandling(async () => {
|
|
42560
|
+
const name = (provider ?? "github").toLowerCase();
|
|
42561
|
+
if (name !== "github") {
|
|
42562
|
+
writeError(`Unknown provider: ${name}. v1 only supports github.`);
|
|
42563
|
+
return;
|
|
42564
|
+
}
|
|
42565
|
+
const p = new GitHubProvider();
|
|
42566
|
+
const s = await p.status();
|
|
42567
|
+
if (!s.linked) {
|
|
42568
|
+
console.log(`Not linked to ${name}. Nothing to do.`);
|
|
42569
|
+
return;
|
|
42570
|
+
}
|
|
42571
|
+
await p.logout();
|
|
42572
|
+
writeSuccess(`Disconnected from ${name}.`);
|
|
42573
|
+
trackEvent("cli_git_auth_disconnect_completed", {
|
|
42574
|
+
provider: name
|
|
42575
|
+
});
|
|
42576
|
+
}, "git-auth-disconnect");
|
|
42577
|
+
}
|
|
42578
|
+
__name(gitAuthDisconnectCommand, "gitAuthDisconnectCommand");
|
|
42579
|
+
function formatLinkedAt(iso) {
|
|
42580
|
+
try {
|
|
42581
|
+
return new Date(iso).toISOString().replace("T", " ").replace(/\..*$/, " UTC");
|
|
42582
|
+
} catch {
|
|
42583
|
+
return iso;
|
|
42584
|
+
}
|
|
42585
|
+
}
|
|
42586
|
+
__name(formatLinkedAt, "formatLinkedAt");
|
|
42587
|
+
|
|
41906
42588
|
// src/commands/pull.ts
|
|
41907
42589
|
init_cli();
|
|
41908
42590
|
init_command_utils();
|
|
@@ -42597,7 +43279,12 @@ Examples:
|
|
|
42597
43279
|
$ lua voice test --runner vitest Force vitest
|
|
42598
43280
|
`).action(voiceTestCommand);
|
|
42599
43281
|
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
|
|
43282
|
+
const versionGroup = program2.command("version").description("\u{1F3F7}\uFE0F Manage agent versions \u2014 atomic snapshots (requires agentVersioningEnabled for your org)").addHelpText("after", `
|
|
43283
|
+
Note:
|
|
43284
|
+
All \`lua version\` subcommands require the \`agentVersioningEnabled\`
|
|
43285
|
+
feature flag for your org. If a subcommand errors with "Agent versioning
|
|
43286
|
+
is not enabled," contact your admin to enable it.
|
|
43287
|
+
`);
|
|
42601
43288
|
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
43289
|
Examples:
|
|
42603
43290
|
$ lua version create Snapshot current state
|
|
@@ -42635,6 +43322,10 @@ Examples:
|
|
|
42635
43322
|
gitGroup.command("connect").description("Enable git auto-commits (runs sanity checks, writes git.enabled: true)").action(() => gitConnectCommand());
|
|
42636
43323
|
gitGroup.command("disconnect").description("Disable git auto-commits (existing commits/tags untouched)").action(() => gitDisconnectCommand());
|
|
42637
43324
|
gitGroup.command("status").description("Show git integration config + last lua-issued commit/tag").action(() => gitStatusCommand());
|
|
43325
|
+
const gitAuthGroup = gitGroup.command("auth").description("Manage git remote provider authentication");
|
|
43326
|
+
gitAuthGroup.command("github").description("Link a GitHub account").option("--device", "Use the device flow (paste a code into github.com/login/device)").option("--force", "Overwrite an existing link without prompting").action((opts) => gitAuthGithubCommand(opts));
|
|
43327
|
+
gitAuthGroup.command("status").description("Show the current git auth status").action(() => gitAuthStatusCommand());
|
|
43328
|
+
gitAuthGroup.command("disconnect [provider]").description("Disconnect a git provider (default: github)").action((provider) => gitAuthDisconnectCommand(provider));
|
|
42638
43329
|
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
43330
|
Examples:
|
|
42640
43331
|
$ lua pull Restore the latest source backup
|